题解 | #不重叠序列检测#---状态机法
不重叠序列检测
https://www.nowcoder.com/practice/9f91a38c74164f8dbdc5f953edcc49cc
思路
状态机如下图所示:
解释一下这个状态机,为什么要这样画呢?
仔细观察波形图,会发现无论匹不匹配,match或者not_match都会隔6个clock cycle变化。所以这正是引入sf1,sf2,sf3....的原因。可以理解为s1,s2,s3....记录匹配的序列,sf1,sf2,sf3....记录不匹配的序列。这样到第6个周期,就能根据当前状态来判断match和not_match了。
代码
`timescale 1ns/1ns module sequence_detect( input clk, input rst_n, input data, output reg match, output reg not_match ); reg [3:0]state; reg [3:0]next_state; localparam IDLE=4'd1, s1=4'd2, sf1=4'd3, s2=4'd4, sf2=4'd5, s3=4'd6, sf3=4'd7, s4=4'd8, sf4=4'd9, s5=4'd10, sf5=4'd11, s6=4'd12, sf6=4'd13; //三段式写法 //第一段 always @(posedge clk or negedge rst_n) begin if (!rst_n)state<=IDLE; else state<=next_state; end //第二段 always @(*) begin//这里括号里应该是* if (!rst_n)next_state<=IDLE; else begin case(state) IDLE:next_state<=data?sf1:s1; s1:next_state<=data?s2:sf2; s2:next_state<=data?s3:sf3; s3:next_state<=data?s4:sf4; s4:next_state<=data?sf5:s5; s5:next_state<=data?sf6:s6; s6:next_state<=data?sf1:s1; sf1:next_state<=sf2; sf2:next_state<=sf3; sf3:next_state<=sf4; sf4:next_state<=sf5; sf5:next_state<=sf6; sf6:next_state<=data?sf1:s1; default:next_state<=IDLE; endcase end end //第三段 always @(posedge clk or negedge rst_n) begin if (!rst_n)begin match<=1'b0; not_match<=1'b0; end else begin if (next_state==s6)begin//这里是next_state不是state match<=1'b1; not_match<=1'b0; end else if (next_state==sf6)begin match<=1'b0; not_match<=1'b1; end else begin match<=1'b0; not_match<=1'b0; end end end endmodule
注意事项
- 第33行,是always(*)不是always @(posedge clk or negedge rst_n)。可以当做三段式的固定写法吧!
- 第61行,是next_state不是state。为什么呢?看下面波形图:
先看图中蓝色竖线左边,此时state是s5,next_state是s6,当蓝色处clk上升沿来时,代码的三段式的第三段和第一段就开始运行。在第三段时,如果第61行是state,而此时state在第一段来不及变化,所以第三段检测到state还是s5,就和我们想要的效果不一样。所以说用next_state不用state.