题意整理

       题目要求检测a的序列,a为单bit输入,每个时刻可能具有不同的值, 当连续的六个输入值符合目标序列表示序列匹配,当六个输入值的一个或多个不符合则表示序列不匹配。

值得注意的是:题目要求以六位数据为一组,不同于常见的序列检测,要求检测重复序列,在画状态转移图时要注意,例如第一位不匹配,不应该返回到初始状态去进行第一位的判断,因为此时的输入是第二位数值,题目要求不对该数值做判断,而需要等到六个时钟周期之后,即第七位数据(第二组数值的第一位)再判断是否匹配目标序列的第一位。

题解主体

       对于序列检测题目,常规的解法有两种:状态机法和序列缓存对比法。

状态机法的过程类似于题意理解中提到的过程:在初始状态中,先判断第一位是否符合,若符合则进入下一个状态,判断第二位是否符合;若第一位不符合则保持在初始状态,直到第一位匹配。如前两位匹配,则判断第三位是否符合,若第一位匹配,最新输入的数值和目标序列的第二位不匹配,则根据最新一位是否匹配第一位,进入第一位匹配状态或者初始状态。依次类推。

序列缓存对比法,则是将六个时刻的数据缓存,作为一个数组,每个时刻的输入位于数组的末尾,数组其它元素左移,把最早输入的数据移出。如果数组和目标序列相等,则说明出现目标序列。拉高match信号,如果不等则拉高not_match信号。

题目要求使用状态机实现,首先画出状态转移图。



sf1,sf2等状态表示该段序列不匹配,此时进行到第n位的对比,当到达sf6,表示已经对比完成全部六位数据,存在不匹配位,拉高not_match。当六位全部对比结束,开始新一轮的对比。s1,s2等状态表示前n位数值匹配,当到达s6时,表示全部数值位匹配,拉高match。X表示不论data的值为0或1,都完成该状态跳变。依据状态转移图编写verilog代码:

reg [3:0] pstate,nstate;

parameter idle=4'd0,

                s1=4'd1,

          s2=4'd2,

          s3=4'd3,

          s4=4'd4,

          s5=4'd5,

          s6=4'd6;

                sf1=4'd7,

          sf2=4'd8,

          sf3=4'd9,

          sf4=4'd10,

          sf5=4'd11,

          sf6=4'd12;

always @(posedge clk or negedge rst_n)

begin

    if(!rst_n)

        pstate<=idle;

    else

        pstate<=nstate;

end

always @(pstate or data)

begin

    case(pstate)

        idle:

            if(data==0)

                nstate=s1;                   //第一位匹配

            else

                nstate=sf1;

        s1:

            nstate=data?s2:sf2;

        s2:

            nstate=data?s3:sf3;

        s3:

            nstate=data?s4:sf4;

        s4:

            nstate=data?sf5:s5;

        s5:

            nstate=data?sf6:s6;

        s6:

            nstate=data?sf1:s1;

        sf1:

            nstate=sf2;

        sf2:

            nstate=sf3;

        sf3:

            nstate=sf4;

        sf4:

            nstate=sf5;

        sf5:

            nstate=sf6;

        sf6:

                     nstate=data?sf1:s1;

        default:

            nstate=idle;

        endcase

end

always @(pstate or data or rst_n)

begin

    if(!rst_n==1)

        match=1'b0;

    else if(pstate==s6)

            match=1'b1;

       else if(pstate==sf6)

            not_match=1'b1;

         else

            match=1'b0;

end

参考答案

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);


reg [3:0] pstate,nstate;

parameter idle=4'd0,
		  s1=4'd1,
          s2=4'd2,
          s3=4'd3,
          s4=4'd4,
          s5=4'd5,
          s6=4'd6,
		  sf1=4'd7,
          sf2=4'd8,
          sf3=4'd9,
          sf4=4'd10,
          sf5=4'd11,
          sf6=4'd12;

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n)
        pstate<=idle;
    else
        pstate<=nstate;
end

always @(pstate or data)
begin
    case(pstate)
        idle:
            if(data==0)
                nstate=s1;			//第一位匹配
            else
                nstate=sf1;
        s1:
            nstate=data?s2:sf2;
        s2:
            nstate=data?s3:sf3;
        s3:
            nstate=data?s4:sf4;
        s4:
            nstate=data?sf5:s5;
        s5:
            nstate=data?sf6:s6;
        s6:
            nstate=data?sf1:s1;
        sf1:
            nstate=sf2;
        sf2:
            nstate=sf3;
        sf3:
            nstate=sf4;
        sf4:
            nstate=sf5;
        sf5:
            nstate=sf6;
        sf6:
			nstate=data?sf1:s1;
        default:
            nstate=idle;
        endcase
end

always @(pstate or data or rst_n)
begin
    if(!rst_n==1) 
		begin
			match=1'b0;
			not_match = 1'b0;
		end
    else if(pstate==s6)
		begin
			match=1'b1;
			not_match = 1'b0;
		end
	else if(pstate==sf6)
		begin
			match=1'b0;
			not_match = 1'b1;
		end
    else
		begin
			match=1'b0;
			not_match = 1'b0;
		end
end

endmodule