HDLbits答案更新系列11(3.2 Sequential Logic 3.2.5 Finite State Machines 3.2.5.1 Simple FSM 1等)

本文深入解析状态机设计,包括两段式与三段式状态机的异同,通过具体实例对比异步复位与同步复位的状态机实现,强调电路设计角度下的最佳实践。

目录

前言

3.2.5 Finite State Machines

3.2.5.1 Simple FSM 1(asynchronous reset)

3.2.5.2 Simple FSM 1(synchronous reset)

3.2.5.3 Simple FSM 2(asynchronous reset)

3.2.5.4 Simple FSM 2(synchronous reset)

结语

HDLbits网站链接


前言

今天终于来到了数字IC设计的另一个重要部分:状态机。对于这部分内容,我可能不会一次更新一个小节,一是因为代码量,二是因为状态机这个小节内容太多了,博主在完成这部分内容时也不是每道题目都很容易就解决了,有几道题目需要深入讲解,所以更新会慢一些,还请大家见谅。当然如果大家有不同的解法,欢迎大家留言~

3.2.5 Finite State Machines

3.2.5.1 Simple FSM 1(asynchronous reset)

module top_module(
    input clk,
    input areset,    // Asynchronous reset to state B
    input in,
    output reg out);//  

    parameter A=1'b0, B=1'b1; 
    reg current_state, next_state;
    
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= B;
        end
        else begin
            current_state <= next_state;
        end
    end

    always@(*)begin
        case(current_state)
            B:begin
                if(in == 1'b1)begin
                    next_state = B;
                end
                else begin
                    next_state = A;
                end
            end
            A:begin
                if(in == 1'b1)begin
                    next_state = A;
                end
                else begin
                    next_state = B;
                end
            end
        endcase
    end
    
    //combinational logic way
    always@(*)begin 
        if(current_state == B)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end
    
    /*
    //second way
    //assign out = (current_state == B);
    */
    
    /*
    //third way
    always@(*)begin
        case(current_state)
            B:begin
                out = 1'b1;
            end
            A:begin
                out = 1'b0;
            end
        endcase
    end
    */    
    
    /*
    //forth way
    //sequential logic way
    always@(posedge clk or posedge areset)begin
        if(areset)begin
            out <= 1'b1;
        end
        else if(next_state == B)begin
            out <= 1'b1;
        end
        else begin
            out <= 1'b0;
        end
    end
    */
    
endmodule

第一题根据状态转移图写代码,这道题目博主给出了四种输出写法,前三种是用组合逻辑输出,最后一种是用时序逻辑输出。注意这道题目时序逻辑复位时的out是状态B。

这里大家一定要明白,虽然从代码结构上来说,这四种方式都可以算作三段式状态机,但是从电路设计的角度来说,只有第四种算是三段式状态机。

两段式状态机的第一个进程是格式化描述次态到现态的转移(即current_state <= next_state),第二个进程是纯组合逻辑描述状态转移条件(即case(current_state)),最后使用组合逻辑对current_state进行判断得到输出结果。

三段式状态机的第一个进程是格式化描述次态到现态的转移(即current_state <= next_state),第二个进程是纯组合逻辑描述状态转移条件(即case(current_state)),第三个进程是使用时序逻辑得到输出结果,注意这里判断的是next_state。

两段式状态机代码简单直观,但是组合逻辑易产生毛刺等不稳定因素,如果电路能够允许一个多余的时序节拍,那么两段式状态机采用寄存器输出是很好的。三段式状态机采用寄存器输出,可以避免毛刺,改善时序条件,但是三段式状态机分割了两部分组合逻辑(状态转移条件组合逻辑和输出组合逻辑),因此这条路径的时序相对紧张。博主个人还是建议大家使用三段式状态机。由于两段式状态机更为简洁,博主为了快速完成题目,后面的题目也使用了较多的两段式状态机,实际应用中还是用三段式多一些。

总之,这两种写法都是博主建议的写法。

3.2.5.2 Simple FSM 1(synchronous reset)

// Note the Verilog-1995 module declaration syntax here:
module top_module(clk, reset, in, out);
    input clk;
    input reset;    // Synchronous reset to state B
    input in;
    output out;//  
    reg out;

    parameter A = 1'b0;
    parameter B = 1'b1;

    reg current_state, next_state;
    
    always@(posedge clk)begin
        if(reset)begin
            current_state <= B;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            B:begin
                if(in == 1'b1)begin
                    next_state = B;
                end
                else begin
                    next_state = A;
                end
            end
            A:begin
                if(in == 1'b1)begin
                    next_state = A;
                end
                else begin
                    next_state = B;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == B)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end


endmodule

这道题目和第一道题目差不多,只是复位换成了同步复位。

3.2.5.3 Simple FSM 2(asynchronous reset)

module top_module(
    input clk,
    input areset,    // Asynchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF = 1'b0, ON = 1'b1; 
    reg current_state, next_state;

    always@(posedge clk or posedge areset)begin
        if(areset)begin
            current_state <= OFF;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            OFF:begin
                if(j == 1'b1)begin
                    next_state = ON;
                end
                else begin
                    next_state = OFF;
                end
            end
            ON:begin
                if(k == 1'b1)begin
                    next_state = OFF;
                end
                else begin
                    next_state = ON;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == ON)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end            

endmodule

这道题目有相比前两道题目多了一个输入,其他没有太多差别。

3.2.5.4 Simple FSM 2(synchronous reset)

module top_module(
    input clk,
    input reset,    // Synchronous reset to OFF
    input j,
    input k,
    output out); //  

    parameter OFF = 1'b0, ON = 1'b1; 
    reg current_state, next_state;

    always@(posedge clk)begin
        if(reset)begin
            current_state <= OFF;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            OFF:begin
                if(j == 1'b1)begin
                    next_state = ON;
                end
                else begin
                    next_state = OFF;
                end
            end
            ON:begin
                if(k == 1'b1)begin
                    next_state = OFF;
                end
                else begin
                    next_state = ON;
                end
            end
        endcase
    end
    
    always@(*)begin
        if(current_state == ON)begin
            out = 1'b1;
        end
        else begin
            out = 1'b0;
        end
    end

endmodule

这道题目相比上一道题目,异步复位变成了同步复位,别的没什么区别。

结语

今天先更新这四道题目,这四道题目是最基础的状态机题目,没有什么特别大的难度,重点是清楚两段式状态机和三段式状态机的异同点,仅从结构考虑(广义上),博主在题目3.2.5.1中的四种写法都属于三段式状态机,但是从电路设计的角度来说,只有第四种写法属于三段式状态机,希望大家能够弄清楚这一点。

如果代码有错误的地方希望大家可以提醒我,我一定尽快改正。

HDLbits网站链接

https://hdlbits.01xz.net/wiki/Main_Page

HDLBits 是一个用于学习硬件描述语言(如 Verilog 和 VHDL)的在线平台,顺序逻辑部分的题目围绕触发器、计数器、状态机等内容展开。以下通过几个典型例子给出答案及解题思路: ### 例 1:D 触发器(D Flip - Flop) 题目要求:创建一个 D 触发器,当上升沿触发时,将输入 `d` 传递到输出 `q`。 解题思路:在 Verilog 中,使用 `always @(posedge clk)` 块来捕捉时钟信号的上升沿,在该块内将输入 `d` 赋值给输出 `q`。 Verilog 代码: ```verilog module top_module ( input clk, // Clock input d, // Input data output reg q // Output data ); always @(posedge clk) begin q <= d; end endmodule ``` 这里使用非阻塞赋值 `<=` 是为了避免在同一时钟周期内的竞争条件。 ### 例 2:4 位同步计数器(4 - bit Synchronous Counter) 题目要求:创建一个 4 位的同步计数器,在时钟上升沿且使能信号 `en` 有效时,计数器加 1。 解题思路:同样使用 `always @(posedge clk)` 块,在使能信号 `en` 为高电平时,对计数器进行加 1 操作。当计数器达到最大值(15,二进制 `4&#39;b1111`)时,可根据需求决定是否复位。 Verilog 代码: ```verilog module top_module ( input clk, input en, output reg [3:0] out ); always @(posedge clk) begin if (en) begin out <= out + 1; end end endmodule ``` ### 例 3:简单的状态机(Simple State Machine) 题目要求:设计一个简单的状态机,有两个状态 `S0` 和 `S1`,在时钟上升沿,根据输入 `in` 进行状态转换。 解题思路:首先定义状态的枚举类型,然后使用 `always @(posedge clk)` 块来实现状态的转换和输出逻辑。 Verilog 代码: ```verilog module top_module ( input clk, input in, output reg out ); // 定义状态 parameter S0 = 1&#39;b0, S1 = 1&#39;b1; reg state, next_state; // 状态转换逻辑 always @(*) begin case (state) S0: next_state = in ? S1 : S0; S1: next_state = in ? S1 : S0; default: next_state = S0; endcase end // 状态更新 always @(posedge clk) begin state <= next_state; end // 输出逻辑 always @(*) begin case (state) S0: out = 1&#39;b0; S1: out = 1&#39;b1; default: out = 1&#39;b0; endcase end endmodule ```
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值