闪光的哈萨维中文小说:序列检测器

来源:百度文库 编辑:偶看新闻 时间:2024/04/19 01:31:28

功能描述:

序列检测器就是将一个指定序列从数字码流中识别出来。本例中将设计一个“10010”序列的检测器。设X为数字码流的输入,Z为检测出标记输出,高电平表示发现指定的序列10010.考虑码流为110010010000100101....则,如表有:

用FSM实现

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273moduleseqdet (    inputwirex,    inputwireclk,    inputwirerst,    outputwirez );   reg[2:0] state;   localparam  IDLE = 3'd0,             A    = 3'd1,             B    = 3'd2,             C    = 3'd3,             D    = 3'd4,             E    = 3'd5,             F    = 3'd6,             G    = 3'd7;   assignz = (state == D && x==0)?1'b1:1'b0;//状态为D时又收到输入0,表明10010已经收到,输出为1   always@ (posedgeclk,negedgerst)    if(!rst)       begin          state <= IDLE;       end   else      casex(state)           IDLE:              if(x==1)                 state <= A;  //状态A记住第一位正确高电平1来过              else                state <= IDLE;           A:              if(x==0)                 state <= B;  //状态B记住第二位正确低电平0来过              else                state <= A;           B:              if(x==0)                 state <= C;  //状态C记住第三位正确低电平0来过              else                state <= F; //输入高电平,不符合要求,F记住只有1位对过           C:              if(x==1)                 state <= D;  //状态D记住第四位正确高电平1来过              else                state <= G;  //输入低电平,不符合要求,G记住没有1为曾经对过           D:              if(x==0)                 state <= E;  //状态E记住第五位正确低电平0来过              else                state <= A;            E:              if(x==0)                 state <= C; //用状态记住100正确来过              else                state <= A;           F:              if(x==1)                 state <= A;              else                state <= B;           G:              if(x==1)                 state <= F;              else                state <= B;         default:                 state <=IDLE;       endcase  endmodule

测试文件:

123456789101112131415161718192021222324252627282930313233`timescale1ns/1ns moduleseqdet_tb; localparamT =20; regclk,rst; reg[23:0] data; wirez,x;   assignx = data[23];   initialbegin    clk =0;     rst =1;     #2 rst =0;     #30 rst =1;     data =20'b1100_1001_0000_1001_0100;     #(T*1000) $stop; end  always#T clk = ~clk;   always@ (posedgeclk)    #2 data = {data[22:0],data[23]};      seqdet U1 (    .x(x),    .z(z),    .clk(clk),    .rst(rst) );   endmodule

用移位寄存器实现检测

1234567891011121314151617181920moduleseqdet (    inputwirex,    inputwireclk,    inputwirerst,    outputwirez,    outputreg[4:0] q );   //reg [4:0] q;   assignz = (q == 5'b10010) ? 1'b1:1'b0;   always@ (posedgeclk,negedgerst)    if(!rst)       q <= 5'd0;    else      q <= {q[3:0],x};   endmodule

RTL级视图:

测试文件:

1234567891011121314151617181920212223242526272829303132333435`timescale1ns/1ns moduleseqdet_tb; localparamT =20; regclk,rst; reg[23:0] data; wirez,x; wire[4:0] q;   assignx = data[23];   initialbegin    clk =0;     rst =1;     #2 rst =0;     #30 rst =1;     data =20'b1100_1001_0000_1001_0100;     #(T*1000) $stop; end  always#T clk = ~clk;   always@ (posedgeclk)    #2 data = {data[22:0],data[23]};      seqdet U1 (    .x(x),    .z(z),    .clk(clk),    .q(q),    .rst(rst) );   endmodule

仿真结果:

NOTE:

由于移位寄存器的赋值是在always块中,故而相对实际延迟了一个clk.

由上面的方针结果可知,输出z相对x晚了一个时钟周期,因为由于移位寄存器的赋值是在always块中,故而相对实际延迟了一个clk.

代码修改如下:

123456789101112131415161718192021moduleseqdet (    inputwirex,    inputwireclk,    inputwirerst,    outputwirez,    outputreg[4:0] q );   wire[4:0] q_next;   assignq_next ={q[3:0],x}; assignz = (q_next== 5'b10010) ? 1'b1:1'b0;   always@ (posedgeclk,negedgerst)    if(!rst)       q <= 5'd0;    else      q <= q_next;   endmodule

状态机修改:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394moduleseqdet (    inputwirex,    inputwireclk,    inputwirerst_n,    outputwirez ); //用verilog设计一个 10010 序列的检测器 reg[4:0] cs,ns; localparam[4:0]    IDLE    =5'd0,                           A     =5'd1,                           B     =5'd2,                           C     =5'd3,                           D     =5'd4,                           E     =5'd5; //状态转移 always@ (posedgeclk,negedgerst_n)     if(!rst_n)         cs  <= IDLE;     else        cs <= ns; //组合逻辑,产生下一状态译码逻辑 always@ (*) begin    ns = 5'bx;     case(cs)         IDLE:             begin                if(x==1)                     ns = A;                 else                    ns = IDLE;             end        A:             begin                if(x==0)                     ns = B;                 else                    ns = A;             end        B:             begin                if(x==0)                     ns = C;                 else                    ns = A;             end        C:             begin                if(x==1)                     ns = D;                 else                    ns = IDLE;             end        D:             begin                if(x==0)                     ns = E;                 else                    ns = A;             end        E:             begin                if(x==0)                     ns = C;                 else                    ns = A;             end        default:             ns = IDLE;     endcaseend//状态寄存输出 /* always @ (posedge clk,negedge rst_n) begin     if(!rst_n)         z <= 1'b0;     else         begin         case(ns)             IDLE,A,B,C,D:   z <= 1'b0;             E               :   z <= 1'b1;             default:    z <= 1'b0;         endcase         end end */  //状态为D时又收到输入0,表明10010已经收到,输出为1   //assign z = (cs == D && x==0)?1'b1:1'b0; assignz = (ns==E);   endmodule