FPGA——关于状态机

状态机,是我大二在实验室学习时,学长给我们安排的任务之一。那个时候,我还没有学过《数电》,一直搞不明白状态机的意思,做了一周,都没有结果。

任务是检测序列,检测到1011时输出一个高电平。

我们都知道verilog语言依靠不同的always语句块实现了硬件电路的并行执行,但是在工程中,我们不仅要处理并行执行电路,偶尔也会遇到需要串行执行的电路要求。刚开始学习FPGA的话,可能会想到我们可以利用很多很多的使能信号实现,但是这样维护的成本大大增加。状态机就可以完美的实现这一功能。先简单介绍一下状态机的基本概念。

状态机的基本要素是输入、输出和状态。输入是引起状态变化的条件,输出是状态变化引起的变化。状态就是字面理解的意思了,状态机,通俗的说就是因为输入导致状态在不断的变化的硬件电路。

Moore型状态机的输出仅与状态有关,与输入无关。
Mealy型状态机的输入不仅与状态有关,还与输入条件有关。
这里写图片描述
一段式写法,输入、输出和状态在一个always语句块中,后期不容易维护。

module pro(
    input   clk,
    input   rst_n,

    input   data,
    output  cntout
);
    parameter   INITIALSTATE = 5'b00_001,
                        STATE_0 = 5'b00_010,
                        STATE_1 = 5'b00_100,
                        STATE_2 = 5'b01_000,
                        STATE_3 = 5'b10_000;



    //————————————————————————————————————————————
    //一段式写法, 既把输入、输出和状态写在一个always语句块                    

    reg[4:0]    state_ce;       //状态寄存器
    reg cnt;
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n)  begin
            cnt <= 1'b0;
            state_ce <= INITIALSTATE;
            end
        else
            case(state_ce)
                INITIALSTATE:   begin
                                            cnt <= 1'b0;
                                            if(data == 1'b1)
                                                state_ce <= STATE_0;
                                            else
                                                state_ce <= INITIALSTATE;
                                            end
                STATE_0:            if(data == 1'b0)
                                            state_ce <= STATE_1;
                                        else
                                            state_ce <= STATE_0;
                STATE_1:            if(data == 1'b1)
                                            state_ce <= STATE_2;
                                        else
                                            state_ce <= INITIALSTATE;
                STATE_2:            if(data == 1'b1)
                                            state_ce <= STATE_3;
                                        else
                                            state_ce <= STATE_1;
                STATE_3:            begin
                                            state_ce <= INITIALSTATE;
                                            cnt <= 1'b1;
                                            end
            endcase
        end

    assign  cntout = cnt;
endmodule

这里写图片描述

二段式写法,分成了组合逻辑和时序逻辑。时序逻辑里作状态的转移,组合逻辑里作输入条件判断和输出。但是组合逻辑输出容易出现毛刺问题。

module pro(
    input   clk,
    input   rst_n,

    input   data,
    output  cntout
);
    parameter   INITIALSTATE = 5'b00_001,
                        STATE_0 = 5'b00_010,
                        STATE_1 = 5'b00_100,
                        STATE_2 = 5'b01_000,
                        STATE_3 = 5'b10_000;

    reg[4:0]    state_ce;
    reg[4:0]    state_nt;
    reg cnt;
    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n)
            state_ce <= INITIALSTATE;
        else
            state_ce <= state_nt;
        end

    always @ (state_ce or data) begin
        case(state_ce)
            INITIALSTATE:   begin
                                        cnt = 1'b0;
                                        if(data == 1'b1)
                                            state_nt = STATE_0;
                                        else
                                            state_nt = INITIALSTATE;
                                        end
            STATE_0:            begin
                                        cnt = 1'b0;
                                        if(data == 1'b0)
                                            state_nt = STATE_1;
                                        else
                                            state_nt = STATE_0;
                                        end
            STATE_1:            begin
                                        cnt = 1'b0;
                                        if(data == 1'b1)
                                            state_nt = STATE_2;
                                        else
                                            state_nt = INITIALSTATE;
                                        end
            STATE_2:            begin
                                        if(data == 1'b1)
                                            state_nt= STATE_3;
                                        else
                                            state_nt =STATE_1;
                                        end
            STATE_3:            begin
                                        cnt = 1'b1;
                                        state_nt = INITIALSTATE;
                                        end         
        endcase
        end


    assign  cntout = cnt;

endmodule

三段式写法,又将输出写作时序逻辑输出,解决了二段式中毛刺的问题。

module pro(
    input   clk,
    input   rst_n,

    input   data,
    output  cntout
);
    parameter   INITIALSTATE = 5'b00_001,
                        STATE_0 = 5'b00_010,
                        STATE_1 = 5'b00_100,
                        STATE_2 = 5'b01_000,
                        STATE_3 = 5'b10_000;

    reg[4:0]    state_ce;
    reg[4:0]    state_nt;
    reg cnt;

    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n)
            state_ce <= INITIALSTATE;
        else
            state_ce <= state_nt;
        end

    always @ (state_ce or data) begin
        case(state_ce)
            INITIALSTATE:   if(data == 1'b1)
                                        state_nt = STATE_0;
                                    else
                                        state_nt = INITIALSTATE;
            STATE_0:            if(data == 1'b0)
                                        state_nt = STATE_1;
                                    else
                                        state_nt = STATE_0;
            STATE_1:            if(data == 1'b1)
                                        state_nt = STATE_2;
                                    else
                                        state_nt = INITIALSTATE;
            STATE_2:            if(data == 1'b1)
                                        state_nt = STATE_3;
                                    else 
                                        state_nt = STATE_2;
            STATE_3:        state_nt = INITIALSTATE;
        endcase
        end

    always @ (posedge clk or negedge rst_n) begin
        if(!rst_n)
            cnt <= 'd0;
        else if(state_nt == STATE_3)
            cnt <= 1'b1;
        else
            cnt <= 1'b0;
        end

    assign  cntout = cnt;
endmodule
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值