FPGA学习状态机实现序列检测

状态机实现序列检测

设计目标:检测输入序列10010并标志

状态转移图

状态机

代码

序列检测

module FSM (
    input wire clk,
    input wire rst_n,
    input wire data_in,
    output reg find_out
);

reg [5:0]state; 
parameter   
    IDLE = 6'b000001,
    S0 = 6'b000010,
    S1 = 6'b000100,
    S2 = 6'b001000,
    S3 = 6'b010000,
    S4 = 6'b100000; 

// //一段式 状态转换和输出
// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n) begin
//        state <= IDLE;
//        find_out <= 1'b0; 
//     end
//     else case (state)
//         IDLE:begin
//             find_out <= 1'b0;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= IDLE;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S0:begin
//             find_out <= 1'b0;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= S1;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S1:begin
//             find_out <= 1'b0;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= S2;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S2:begin
//             find_out <= 1'b0;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= IDLE;
//             end
//             else begin
//                 state <= S3;
//             end
//         end
//         S3:begin
//             find_out <= 1'b0;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= S4;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S4:begin
//             find_out <= 1'b1;
//             if (~rst_n) begin
//                 state <= IDLE;
//             end
//             else if (data_in == 1'b0) begin
//                 state <= S2;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//     endcase

// end


// //二段式 
// //状态转化
// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n) begin
//        state <= IDLE; 
//     end
//     else case (state)
//         IDLE:begin
//             if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= IDLE;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S0:begin
//            if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= S1;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S1:begin
//            if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= S2;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S2:begin
//             if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= IDLE;
//             end
//             else begin
//                 state <= S3;
//             end
//         end
//         S3:begin
//             if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= S4;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//         S4:begin
//             if(~rst_n)begin
//                 state <= IDLE;
//             end 
//             else if (data_in == 1'b0) begin
//                 state <= S2;
//             end
//             else begin
//                 state <= S0;
//             end
//         end
//     endcase
// end
// //结果输出
// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n) begin
//        find_out <= 1'b0; 
//     end
//     else case (state)
//         IDLE:find_out <= 1'b0;
            
//         S0:find_out <= 1'b0;
            
//         S1:find_out <= 1'b0;
           
//         S2:find_out <= 1'b0;
           
//         S3:find_out <= 1'b0;
           
//         S4:find_out <= 1'b1;
        
//         default:find_out <= 1'b0;
//     endcase
// end

//三段式
reg [5:0]current_state;
reg [5:0]next_state;

//第一段时序逻辑
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        current_state <= IDLE;
    end
    else begin
        current_state <= next_state;
    end
end

//组合逻辑表示状态转移
always @(*) begin
    case (current_state)
        IDLE:begin
            if (~rst_n) begin
                next_state = IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state = IDLE;
            end
            else begin
                next_state = S0;
            end
        end
        S0:begin
            if (~rst_n) begin
                next_state <= IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state <= S1;
            end
            else begin
                next_state <= S0;
            end
        end
        S1:begin
            if (~rst_n) begin
                next_state <= IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state <= S2;
            end
            else begin
                next_state <= S0;
            end
        end
        S2:begin
            if (~rst_n) begin
                next_state <= IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state <= IDLE;
            end
            else begin
                next_state <= S3;
            end
        end
        S3:begin
            if (~rst_n) begin
                next_state <= IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state <= S4;
            end
            else begin
                next_state <= S0;
            end
        end
        S4:begin
            if (~rst_n) begin
                next_state <= IDLE;
            end
            else if (data_in == 1'b0) begin
                next_state <= S2;
            end
            else begin
                next_state <= S0;
            end
        end
        // IDLE: next_state = data_in ? S0 : IDLE;
        // S0: next_state = data_in ? S0 : S1;
        // S1: next_state = data_in ? S0 : S2;
        // S2: next_state = data_in ? S3 : IDLE;
        // S3: next_state = data_in ? S0 : S4;
        // S4: next_state = data_in ? S0 : S2;
        // default: next_state = IDLE;
    endcase
end
//结果输出
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
       find_out <= 1'b0; 
    end
    else case (current_state)
        IDLE:find_out <= 1'b0;
            
        S0:find_out <= 1'b0;
            
        S1:find_out <= 1'b0;
           
        S2:find_out <= 1'b0;
           
        S3:find_out <= 1'b0;
           
        S4:find_out <= 1'b1;
        
        default:find_out <= 1'b0;
    endcase
end
endmodule

tb文件

`timescale 1ns/1ps

module FSM_tb ();
    
reg clk;
reg rst_n;
reg data_in;
wire find_out;


initial begin
    clk = 1'b0;
    rst_n = 1'b0;
    data_in = 1'b0;
    #10
    rst_n = 1'b1;
end

always #10 clk = ~clk;

always #20 data_in = {$random} % 2; 

FSM FSM_1(
    .clk(clk),
    .rst_n(rst_n),
    .data_in(data_in),
    .find_out(find_out)
);

endmodule

仿真结果

仿真

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值