题解 | #输入序列连续的序列检测#
Tips
三段式状态机的第一段状态流转的功能是使state_cur比state_next慢一拍,也就是说,第一段实际上就是一个D触发器。如果要让输出也慢一拍,那么让输出端也类似地构造一个D触发器输出就可以了。
Verilog Code
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
//行为描述
reg [2:0] state_cur = 3'd0, state_next = 3'd0;
reg [2:0] S0 = 3'd0, S1 = 3'd1, S2 = 3'd2, S3 = 3'd3;
reg [2:0] S4 = 3'd4, S5 = 3'd5, S6 = 3'd6, S7 = 3'd7;
reg [1:0] cnt = 2'd0;
reg tag = 1'b0;
//状态流转
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
state_cur <= 3'd0;
end
else begin
state_cur <= state_next;
end
end
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
match <= 1'b0;
end
else begin
match <= tag;
end
end
//状态切换
always @(*)begin
if(~rst_n)begin
state_next = 3'd0;
end
else begin
case(state_cur)
S0: state_next = (a == 1'd0 ? S1:S0);
S1: state_next = (a == 1'd1 ? S2:S1);
S2: state_next = (a == 1'd1 ? S3:S1);
S3: state_next = (a == 1'd1 ? S4:S1);
S4: state_next = (a == 1'd0 ? S5:S0);
S5: state_next = (a == 1'd0 ? S6:S2);
S6: state_next = (a == 1'd0 ? S7:S2);
S7: state_next = (a == 1'd1 ? S0:S1);
default:state_next = S0;
endcase
end
end
//状态输出
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
tag <= 1'b0;
end
else begin
if(state_cur == S7 && a == 1'b1)begin
tag <= 1'b1;
end
else begin
tag <= 1'b0;
end
end
end
endmodule
Testbench Code
`timescale 1ns/1ns
module testbench();
reg clk,rst_n;
reg a;
wire match;
initial begin
$dumpfile("out.vcd");
$dumpvars(0,testbench);
clk = 1'b1;
rst_n = 0;
end
always #5 clk = ~clk;
initial begin
#10 rst_n = 1'b1;
a = 0;
#10 a = 1'b1;
#30 a = 0;
#30 a = 1'b1;
#10 a = 0;
#20 $finish();
end
sequence_detect dut(
.clk(clk),
.rst_n(rst_n),
.a(a),
.match(match)
);
endmodule