首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HDLBits:在线学习 Verilog (二十二 · Problem 105 - 109)

HDLBits:在线学习 Verilog (二十二 · Problem 105 - 109)

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

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

Problem 105 12-hour clock

牛刀小试

用计数器设计一个带am/pm的12小时时钟。该计数器通过一个CLK进行计时,用ena使能信号来驱动时钟的递增。

reset信号将时钟复位为12:00 AM。信号pm为0代表AM,为1代表PM。hh、mm和ss由两个BCD计数器构成hours(01~12), minutes(00~59) , second(00~59)。Reset信号比enable信号有更高的优先级,即使没有enable信号也可以进行复位操作。

下图所示的时序图给出了从11:59:59 AM 到12 :00 : 00 PM的变化。

Hint

需要注意的是从11:59:59 PM 到12:00:00 AM和从12:59:59 PM到01:00:00 PM的变化。

解答与解析

module top_module
    (
        input clk,
        input reset,
        input ena,
        output pm,
        output [7:0] hh,
        output [7:0] mm,
        output [7:0] ss
    );

reg p;  //0 is am, 1 is pm
reg [7:0] h;
reg [7:0] m;
reg [7:0] s;

always @ (posedge clk)
    begin
        if(reset)   //reset to 12:00:00 AM
            begin
                p <= 0;
                h <= 8'h12;
                m <= 8'h00;
                s <= 8'h00;
            end
        else
            begin
                if(ena)
                    begin
                        if(s < 8'h59)
                            begin
                                if(s[3:0] < 4'h9)   //s[3:0] is ones digit
                                    begin
                                        s[3:0] <= s[3:0] + 1'h1;
                                    end
                                else
                                    begin
                                        s[3:0] <= 0;    //59->00
                                        s[7:4] <= s[7:4] + 1'h1; //tens digit
                                    end 
                            end
                        else
                            begin
                                s <= 0; //s清零
                                if(m < 8'h59)   //m同理s
                                    begin
                                        if(m[3:0] < 4'h9)
                                            begin
                                                m[3:0] <= m[3:0] + 1'h1;
                                            end 
                                        else
                                            begin
                                                m[3:0] <= 0;
                                                m[7:4] <= m[7:4] + 1'h1;
                                            end
                                    end
                                else
                                    begin
                                        m <= 1'h0;
                                        if(h == 8'h11)  //AM / PM 转换
                                            p = !p;
                                        if(h < 8'h12)
                                            begin
                                                if(h[3:0] < 4'h9)
                                                    h[3:0] <= h[3:0] + 1'h1;
                                                else
                                                    begin
                                                        h[3:0] <= 4'h0;
                                                        h[7:4] <= h[7:4] + 1'h1;
                                                    end
                                            end
                                        else
                                            begin //hour 12 -> 1
                                                h <= 1'h1;
                                            end
                                    end
                            end
                    end
            end
    end

assign pm = p;
assign hh = h;
assign mm = m;
assign ss = s;

endmodule

Problem 106 4-bit shift register

牛刀小试

设计一个4bit异步复位,拥有同步置位和使能的右移移位寄存器。

  • areset : 寄存器复位为0
  • load : 将data[3:0]输入至移位寄存器中
  • ena : 使能信号控制向右移动(q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1],q[0]在移动后消失了,原先q[3]的位置变为0)
  • q : 移位寄存器中的数据

如果ena和load同时为高,load有更高的优先级。

解答与解析

本题为4-bit的移位寄存器,在ena信号中所举例子可以很好说明本题要求。q[3]q[2]q[1]q[0] ---> 0q[3]q[2]q[1]。

module top_module(
    input clk,
    input areset,  // async active-high reset to zero
    input load,
    input ena,
    input [3:0] data,
    output reg [3:0] q);

    always @ (posedge clk or posedge areset)
        begin
            if(areset)
                q <= 4'b0;
            else if (load)
                q <= data;
            else if (ena)
                begin
                    q[3:0] <= {1'b0, q[3:1]};
                    //q[3]q[2]q[1]q[0] -->  0q[3]q[2]q[1],q[0]在移动后消失了,原先q[3]的位置变为0
                end
        end

endmodule

Problem 107 Left/right rotator

牛刀小试

设计一个100bit的可左移或右移的移位寄存器,附带同步置位和左移或右移的使能信号。本题中,移位寄存器在左移或右移时,不同于Problem106的补0和直接舍弃某一bit位,本题是要求在100bit内循环移动,不舍弃某一bit位同时也不补0。

比如说左移1bit,在Problem106就是补0和丢弃q[0]。而在本题中左移1bit为{q[0], q[99:1]}。

  • load:load信号将data[99:0] 输入至寄存器内。
  • ena[1:0] 信号选择是否移位和移位的具体方向
  • 2'b01 右移一位
  • 2'b10 左移一位
  • 2'b00 和 2'b11不移动
  • q:移位后寄存器内的数据

解答与解析

module top_module(
    input clk,
    input load,
    input [1:0] ena,
    input [99:0] data,
    output reg [99:0] q);

    always @ (posedge clk)
        begin
            if(load)
                q <= data;
            else if (ena == 2'b01)
                q <= {q[0], q[99:1]};
            else if (ena == 2'b10)
                q <= {q[98:0], q[99]};
            else if (ena == 2'b00 || ena == 2'b11)
                q <= q;
        end

endmodule

Problem 108 Left/right arithmetic shift by 1 or 8

牛刀小试

设计一个64-bit带同步置位的算术移位寄存器。该寄存器可以由amount控制来移动方向和每次移动的次数。

算术右移移位寄存器中的符号位(q [63])移位,不像是逻辑右移中进行补零的操作。而是保留符号位后再进行移位。

Hint

一个5-bit值为11000的寄存器算术右移一位后为11100, 而逻辑右移后为01100。

同样的,一个5-bit值为01000的寄存器算术右移一位后为00100,且该寄存器逻辑右移会产生同样的结果。

逻辑移位寄存器和算术左移移位寄存器没有区别。

  • load :置位信号。
  • ena :使能信号,来选择是否移位
  • amount :选择移位的方向和移位的个数
  • 2'b00 : 左移1bit
  • 2’b01 : 左移8bit
  • 2'b10 : 右移1bit
  • 2'b11 : 右移8bit
  • q :寄存器中哦的数据

解答与解析

module top_module(
    input clk,
    input load,
    input ena,
    input [1:0] amount,
    input [63:0] data,
    output reg [63:0] q);

    always @ (posedge clk)
        begin
            if(load)
                q <= data;
            else if (ena)
                begin
                    case(amount)
                        2'b00 :     begin
                            q <= {q[62:0], 1'b0};
                        end

                        2'b01:  begin
                            q <= {q[55:0], 8'b0};
                        end

                        2'b10: begin
                            q <= {q[63], q[63:1]};
                        end

                        2'b11: begin
                            q <= {{8{q[63]}}, q[63-:56]};
                            //算术右移是用符号位填充和q的高56位
                            //{{8{q[63]}}, q[63-:56]}
                        end
                    endcase
                end
        end

endmodule

Problem 109 5-bit LFSR

牛刀小试

线性反馈移位寄存器(LFSR)是通常带有几个XOR门来产生下一状态的移位寄存器。Galois LFSR是一个特殊的移位寄存器。其中带有"tap"位的位置与输出位XOR产生下一个值没有"tap"位标志的正常移位。如果"tap"位置经过仔细选择后,LFSR将设置为最大长度。再重复之前LFSR的最大长度为2^n-1

下图所示LFSR为在位置5和位置3包含"tap"位的5-bit最大长度LFSR。开始为位置1,输入为0。

设计如上图所示LFSR,复位信号使LFSR复位为1.

module top_module(
    input clk,
    input reset,    // Active-high synchronous reset to 5'h1
    output [4:0] q
);
    always @ (posedge clk)
        begin
            if(reset)
                q <= 5'b00001;
            else
                begin
                    q[4] <= 1'b0 ^ q[0];
                    q[3] <= q[4];
                    q[2] <= q[3] ^ q[0];
                    q[1] <= q[2];
                    q[0] <= q[1];
                end
        end

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

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

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

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

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