题解 | #输入序列不连续的序列检测#
序列检测一般有两种办法,一种是利用移位寄存器来实现,这种方法比较简单。另一种是利用状态机来实现,难点在于状态转移图的绘制。下面使用状态机来实现,
首先画出状态转移图
然后根据状态转移图,写出三段式状态机,鉴于data_valid控制data是否有效,我采用使用data_valid来控制状态机的转移,当data_valid有效时,状态机正常跳转,否则状态机回归初始状态S0。代码如下:
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output match
);
parameter S0 = 4'd0,
S1 = 4'd1,
S2 = 4'd2,
S3 = 4'd3,
S4 = 4'd4;
reg [3:0] curr_state,next_state;
//状态跳转
always@(posedge clk or negedge rst_n)begin
if(rst_n == 0)
curr_state <= S0;
else if(data_valid) //控制状态机跳转
curr_state <= next_state;
else
curr_state <= curr_state;
end
//状态转移逻辑
always@(*)begin
case(curr_state)
S0:next_state = data ? S0 : S1 ;
S1:next_state = data ? S2 : S1 ;
S2:next_state = data ? S3 : S1 ;
S3:next_state = data ? S0 : S4 ;
S4:next_state = data ? S2 : S1 ;
default:next_state = S0;
endcase
end
//输出,使用时序将match延后一个周期,不延后可以用assign match = (curr_state == S8);
//注意,使用assign需将match类型改为wire
/*always@(posedge clk or negedge rst_n) begin
if(rst_n == 0)
match <= 0;
else
match = (curr_state == S4);
end*/
assign match = (curr_state == S4);
endmodule