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