前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HDLBits:在线学习 Verilog (二十九 · Problem 140-144)

HDLBits:在线学习 Verilog (二十九 · Problem 140-144)

作者头像
数字积木
发布2021-04-15 14:58:28
5730
发布2021-04-15 14:58:28
举报
文章被收录于专栏:数字积木

本系列内容来自于知乎专栏,链接如下:https://zhuanlan.zhihu.com/c_1131528588117385216 本系列文章将和读者一起巡礼数字逻辑在线学习网站 HDLBits 的教程与习题,并附上解答和一些作者个人的理解,相信无论是想 7 分钟精通 Verilog,还是对 Verilog 和数电知识查漏补缺的同学,都能从中有所收获。

Problem 140 Serial two's complementer (Mealy FSM)

牛刀小试

本题和上一题 Serial two's complementer (Moore FSM) 一样,使用状态机实现一个二进制补码生成器,不同的是此题使用米里型状态机实现。

在本题与上一题中的米里型和摩尔型状态机最简单的区别在于:两者在输出时,摩尔型 FSM 有一个周期延迟。

米里型的输出由当前状态和输入信号的组合逻辑实现,输出信号与输入信号同步。

而摩尔型状态机的输出仅由当前状态决定,与输入信号异步,往往存在延迟。

图片来自下方链接文章,出处见水印

有关两种状态机的知识,大家可以移步下方的文章。

Power小强:FPGA菜鸟学习笔记——4、有限状态机zhuanlan.zhihu.com

书归正传,本题中给出了状态转移图,我们可以直接看图实现状态机。

存在两个状态,复位状态 A,在输入 x 为 1 后状态转移为 B,并保持在状态 B。

状态 A 中输出 z 与输入 x 相同;状态 B 中输出 z 与输入 x 相反。

简单的状态机,但这是如何实现二进制补码的呢?我们根据例子来看:

代码语言:javascript
复制
输入序列为:001101000,即原码,补码通过将原码取反加 1 实现。
取反:             110010111
加 1              110011000

将原码和补码放在一起观察:

代码语言:javascript
复制
001101    000
110011    000

可以发现前半部两者取反,而后半部分两者相同(均为0),两者的分界即是低位第一个 1 。所以有了上图中的状态转移图。

这里我们没有深究原理,只是从状态机的角度出发来实现该题目。(老实说一开始笔者也没想出来如何用状态机来实现这个电路 `_`)

解答与分析

代码语言:javascript
复制
module top_module (
    input clk,
    input areset,    // Asynchronous active-low reset
    input x,
    output z ); 

    reg [1:0]   state;
    reg [1:0]   nxt_state;

    localparam A = 0;
    localparam B = 1;

    // State transition logic (combinational)
    always @(*) begin
        case (state)
            A:begin
                if(x)
                    nxt_state = B;
                else
                    nxt_state = A;
            end
            B:begin
                nxt_state = B;
            end
          default: begin
            nxt_state = A;
          end
        endcase
    end

    // State flip-flops (sequential)
    always @(posedge clk or posedge areset) begin
        if(areset)
            state   <=  A;
        else begin
            state   <=  nxt_state;
        end  
    end
	
    //output logic
    assign  z    =   state == A ? x:~x ;
endmodule

使用独热码的方式实现了一个双状态状态机。输出 z 取决于状态以及输入信号 x,z = x 或者 z = ~x

Problem 141 Q3a:FSM

牛刀小试

接下来一系列题目是状态机的练习题,出处应该是原作者任教学校的考试题目,适合初学者巩固状态机的编码能力。对于一定基础的学习者来说适合进行一次快速通过 Fast Through.(也适合国内高校的相关课程学习一下)

本题需要实现一个双状态状态机,状态转移并不复杂,由输入变量 s 决定。

稍显复杂的是输出逻辑,由输入变量 w 决定。当处于状态 B 时,以三个时钟为一个周期,如果三个周期中有两个周期 w 为 1,则 z 输出一个周期高电平。

值得注意的是:需要三个周期中 exactly 两个周期为 1 。

解答与分析

代码语言:javascript
复制
module top_module (
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output z
);

    reg [3:0]   state;
    reg [3:0]   nxt_state;

    wire        w_shft_ena;
    reg[1:0]    w_cntr;
    localparam A = 0;
    localparam B = 1;
    localparam B1 = 2;
    localparam B2 = 4;

    // State transition logic (combinational)
    always @(*) begin
        case (state)
            A:begin
                if(s)
                    nxt_state = B;
                else
                    nxt_state = A;
            end
            B:begin
                nxt_state = B1;
            end
            B1:begin
                nxt_state = B2;
            end
            B2:begin
                nxt_state = B;
            end
          default: begin
            nxt_state = A;
          end
        endcase
    end

    // State flip-flops (sequential)
    always @(posedge clk ) begin
        if(reset)
            state   <=  A;
        else begin
            state   <=  nxt_state;
        end  
    end

    always @(posedge clk ) begin
        if(reset)
            w_cntr   <=  2'b0;
        else if(state == B)begin
            w_cntr   <=  w;
        end
        else if(state == B1 || state == B2)begin
            w_cntr   <=  w_cntr + w;
        end   
    end

    assign  z    =   state == B &&  w_cntr == 2 ? 1'b1 : 1'b0;

endmodule

实现中值的注意的是,为了便于每三个时钟为一个单位检查输入 w 的值。笔者将状态 B 划分为 B1 B2 B3 三个子状态。使用计数器 w_cntr 在子状态中统计 w 为 1 的次数。

输出阶段为 B1 状态,当计数器值为 2 时输出 1,对应于 三个周期中 exactly 两个周期为 1

Problem 142 Q3b:FSM

牛刀小试

这是一道简单的根据状态转移实现状态机的题目,实现完整的三段式状态机

解答与分析

代码语言:javascript
复制
module top_module (
    input clk,
    input reset,    // Asynchronous active-low reset
    input x,
    output z ); 
    
    `define STT_W 3
    `define STT_W1 `STT_W - 1

    reg [`STT_W1:0]   state;
    reg [`STT_W1:0]   nxt_state;

    localparam IDLE  = `STT_W'd0;
    localparam s_1   = `STT_W'd1;
    localparam s_10  = `STT_W'd2;
    localparam s_11  = `STT_W'd3;
    localparam s_100 = `STT_W'd4;

    // State transition logic (combinational)
    always @(*) begin
        case (state)
            IDLE:begin
                if(x)
                    nxt_state = s_1;
                else
                    nxt_state = IDLE;
            end
            s_1:begin
                if(x)
                    nxt_state = s_100;
                else
                    nxt_state = s_1;
            end
            s_10:begin
                if(x)
                    nxt_state = s_1;
                else
                    nxt_state = s_10;
            end
            s_11:begin
                if(x)
                    nxt_state = s_10;
                else
                    nxt_state = s_1;
            end
            s_100:begin
                if(x)
                    nxt_state =s_100;
                else
                    nxt_state = s_11;
            end
          default: begin
            nxt_state = IDLE;
          end
        endcase
    end

    // State flip-flops (sequential)
    always @(posedge clk ) begin
        if(reset)
            state   <=  IDLE;
        else begin
            state   <=  nxt_state;
        end  
    end

    assign  z    =   state >= s_11;

endmodule

有没有巩固自己的状态机编码能力或者 Fast Through 呢?

Problem 143 Q3c:FSM logic

牛刀小试

本题和前一题的区别在于,本题的当前状态于端口输入,只需要实现三段式中的状态跳转逻辑以及输出逻辑,不需要实现状态触发器。

我看过了,状态转移同上一题相同

解答与分析

代码语言:javascript
复制
module top_module (
    input clk,
    input [2:0] y,
    input x,
    output Y0,
    output z
);
    
    `define STT_W 3
    `define STT_W1 `STT_W - 1

    wire [`STT_W1:0]   state = y;
    reg [`STT_W1:0]   nxt_state;

    localparam IDLE  = `STT_W'd0;
    localparam s_1   = `STT_W'd1;
    localparam s_10  = `STT_W'd2;
    localparam s_11  = `STT_W'd3;
    localparam s_100 = `STT_W'd4;

    // State transition logic (combinational)
    always @(*) begin
        case (state)
            IDLE:begin
                if(x)
                    nxt_state = s_1;
                else
                    nxt_state = IDLE;
            end
            s_1:begin
                if(x)
                    nxt_state = s_100;
                else
                    nxt_state = s_1;
            end
            s_10:begin
                if(x)
                    nxt_state = s_1;
                else
                    nxt_state = s_10;
            end
            s_11:begin
                if(x)
                    nxt_state = s_10;
                else
                    nxt_state = s_1;
            end
            s_100:begin
                if(x)
                    nxt_state =s_100;
                else
                    nxt_state = s_11;
            end
          default: begin
            nxt_state = IDLE;
          end
        endcase
    end
    
    assign  Y0   =   nxt_state[0];
    assign  z    =   state >= s_11;

endmodule

输入端口中的 y 输入当前状态,按照题目要求输出次状态最低位 Y0

Problem 144 Q6b:FSM next-state logic

牛刀小试

下图为状态机状态转移图。本题需要根据状态转移图以及输入的当前状态 y[3:1]实现状态跳转逻辑,输出次状态的一部分 Y2.

状态机中共有 6 个状态 A - F 分别用 000,001... 101 表示。使用二进制方式编码状态。

解答与分析

代码语言:javascript
复制
module top_module (
    input [3:1] y,
    input w,
    output Y2);
    
    `define STT_W 3
    `define STT_W1 `STT_W - 1

    wire [`STT_W1:0]   state = y;
    reg [`STT_W1:0]   nxt_state;

    localparam sA  = `STT_W'd0;
    localparam sB  = `STT_W'd1;
    localparam sC  = `STT_W'd2;
    localparam sD  = `STT_W'd3;
    localparam sE  = `STT_W'd4;
    localparam sF  = `STT_W'd5;

    // State transition logic (combinational)
    always @(*) begin
        case (state)
            sA:begin
                if(w)
                    nxt_state = sA;
                else
                    nxt_state = sB;
            end
            sB:begin
                if(w)
                    nxt_state = sD;
                else
                    nxt_state = sC;
            end
            sC:begin
                if(w)
                    nxt_state = sD;
                else
                    nxt_state = sE;
            end
            sD:begin
                if(w)
                    nxt_state = sA;
                else
                    nxt_state = sF;
            end
            sE:begin
                if(w)
                    nxt_state = sD;
                else
                    nxt_state = sE;
            end
            sF:begin
                if(w)
                    nxt_state = sD;
                else
                    nxt_state = sC;
            end
          default: begin
            nxt_state = sA;
          end
        endcase
    end
 
    assign  Y2   =   nxt_state[1];
    
endmodule

值得注意的是 Y2 输出的是对应 Y[2] 的次态,但 Y 在输入时取的是 Y[3:1] ,所以 Y2 取次态 nxt_state[1] 而不是 nxt_state[2]。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数字积木 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档