ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDLBits第十一章练习及答案

2021-09-23 17:03:38  阅读:212  来源: 互联网

标签:reset enable clk HDLBits 第十一章 练习 计数器 ones input


时序逻辑2:计数器

1、四位二进制计数器

构建一个从0到15的4位二进制计数器,周期为16。同步复位,复位应该将计数器重置为0。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,      // Synchronous active-high reset
    output [3:0] q);
	
    always@(posedge clk) begin
        if(!reset)
        	q <= q + 1'b1;
        else
            q <= 4'b0;
    end
        
endmodule

验证结果:
在这里插入图片描述

2、十进制计数器1

构建一个从0到9(包括9)的十进制计数器,其周期为10。同步复位,复位应该将计数器重置为0。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,        // Synchronous active-high reset
    output [3:0] q);

    always@(posedge clk) begin
        if(reset)
            q <= 4'b0;
        else begin
            if(q < 9)
                q <= q + 1'b1;
            else
                q <= 4'b0;
        end         
    end
    
endmodule

验证结果:
在这里插入图片描述

3、十进制计数器2

制作一个从1到10的10进制计数器。同步复位,复位应该将计数器复位为1。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,
    output [3:0] q);

    always@(posedge clk) begin
        if(reset)
           q <= 4'd1; 
        else begin
            if(q < 10)
                q <= q + 1'b1;
            else
                q <= 4'd1;
        end  
    end
    
endmodule

验证结果:
在这里插入图片描述

4、延迟十进制计数器

构建一个从0到9(包括9)的十进制计数器,其周期为10。同步复位,复位应该将计数器重置为0。我们希望能够暂停计数器,而不是总是在每个时钟周期中递增,因此slowena输入指示计数器应该何时递增。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);

    always@(posedge clk) begin
        if(reset)
            q <= 4'b0;
        else 
            if(slowena) begin
                if(q == 4'd9)
                    q <= 4'b0;
                else
                    q<= q + 1'b1;
            end
    end
    
endmodule

验证结果:
在这里插入图片描述
在这里插入图片描述

5、1-12的计数器

设计一个具有以下输入和输出的 1-12 计数器:
Reset :同步高电平有效复位,强制计数器为 1
Enable: 计数器运行设置为高电平
Clk: 上升沿触发时钟输入
Q[3:0] :计数器的输出
c_enable, c_load, c_d[3:0]:控制信号到提供的4位计数器,这样就可以验证操作是否正确。

您可以使用以下组件:

(1)下面的4位二进制计数器(coun4),它具有使能和同步并行负载输入(负载优先级高于使能)。count4模块提供给您。在你的电路中实例化它。
(2)逻辑门

module count4(
	input clk,
	input enable,
	input load,
	input [3:0] d,
	output reg [3:0] Q
);

c_enable、c_load和c_d输出分别是到内部计数器的enable、load和d输入的信号。它们的目的是为了检查这些信号的正确性。

代码实现:

module top_module (
    input clk,
    input reset,
    input enable,
    output [3:0] Q,
    output c_enable,
    output c_load,
    output [3:0] c_d
); 

    assign c_enable = enable;
    assign c_load = reset | ((Q == 4'd12) && (enable == 1'b1));
    assign c_d = c_load ? 4'b1 : 4'b0;
    
    count4 counter(clk,c_enable,c_load,c_d,Q);
    
endmodule

验证结果:
在这里插入图片描述

6、 1kHz→1Hz 计数器

从 1000 Hz 时钟导出一个 1 Hz 信号,称为OneHertz,可以用来驱动一组小时/分钟/秒计数器的启用信号,以创建一个数字挂钟。因为我们想让时钟每秒计数一次,所以 1 Hz 信号必须精确地保持每秒一个周期。建立分频器使用模10 (BCD)计数器和尽可能少的其他门。还从您使用的每个 BCD 计数器输出启用信号(c_enable[0] 表示最快的计数器,c_enable[2] 表示最慢的计数器)。
为您提供了以下 BCD 计数器。Enable必须为高电平才能运行计数器。复位是同步的并设置为高电平以强制计数器归零。电路中的所有计数器必须直接使用相同的 1000 Hz 信号。

module bcdcount (
	input clk,
	input reset,
	input enable,
	output reg [3:0] Q
);

代码实现:

module top_module (
    input clk,
    input reset,
    output OneHertz,
    output [2:0] c_enable
); 

    wire [3:0] one,ten,hundred;
    assign c_enable = {one ==4'd9 && ten == 4'd9, one ==4'd9 ,1'd1};
    assign OneHertz = {one ==4'd9 && ten == 4'd9 && hundred ==4'd9};
        
    bcdcount counter0 (clk, reset, c_enable[0],one);
    bcdcount counter1 (clk, reset, c_enable[1],ten);
    bcdcount counter2 (clk, reset, c_enable[2],hundred);

endmodule

验证结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7、 四位十进制计数器

构建一个4位BCD(二进制编码的十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是个位,q[7:4]是十位,以此类推。各进制上的进位时也需输出一个使能信号,指示三位数字何时应该增加。
在这里插入图片描述
代码实现:

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    reg [3:0] ones,tens,hundreds,thousands;
    
    always @(posedge clk) begin
        if(reset)
            ones <= 4'b0;
        else if(ones == 4'd9)
            ones <=4'b0;
        else
            ones <= ones + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            tens <= 4'b0;
        else if(tens == 4'd9 && ones == 4'd9)
            tens <= 4'b0;
        else if(ones == 4'd9)
            tens <= tens + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            hundreds <= 4'b0;
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            hundreds <= 4'b0;
        else if(tens == 4'd9 && ones == 4'd9) 
            hundreds <= hundreds + 4'd1;
    end
    
    always @(posedge clk)begin
        if(reset)
            thousands <= 4'b0;
        else if(thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            thousands <= 4'b0;
        else if(hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9)
            thousands <= thousands + 4'd1;
    end
    
    assign q = {thousands,hundreds,tens,ones};
    assign ena[1] = (ones == 4'd9) ? 1'b1 : 1'b0;
    assign ena[2] = ((ones == 4'd9) && (tens == 4'd9)) ? 1'b1 : 1'b0;
    assign ena[3] = ((ones == 4'd9) && (tens == 4'd9) && (hundreds == 4'd9)) ? 1'b1 : 1'b0;
    
endmodule

验证结果:
在这里插入图片描述
在这里插入图片描述

8、 12小时的时钟

创建一组适合作为12小时的时钟使用的计数器(带有am/pm指示器)。你的计数器是由一个快速运行的clk驱动,每次时钟增加时ena必须为1。reset将时钟重置到中午12点。上午时pm=0,下午时pm=0。hh,mm和ss分别是小时(01-12)、分钟(00-59)和秒(00-59)的两个BCD(二进制编码的十进制)数字。

Reset比enable具有更高的优先级,并且即使在没有启用时也会发生。

下面的时序图显示了从11:59:59 AM到12:00:00 PM的翻转行为以及同步的Reset和enable行为。
在这里插入图片描述
代码实现:

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    reg pm_temp;
    reg [3:0] ss_ones,ss_tens,mm_ones,mm_tens,hh_ones,hh_tens;
    
    wire	add_ss_ones,end_ss_ones,add_ss_tens,end_ss_tens;
    wire	add_mm_ones,end_mm_ones,add_mm_tens,end_mm_tens;
    wire	add_hh_ones,end_hh_ones_0,end_hh_ones_1,add_hh_tens,end_hh_tens_0,end_hh_tens_1;
    wire	pm_ding;
    
    assign add_ss_ones = ena;
    assign end_ss_ones = add_ss_ones && (ss_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)begin
            ss_ones <= 4'b0;
        end
        else if(add_ss_ones)begin
            if(end_ss_ones)
                ss_ones <= 4'b0;
            else 
                ss_ones <= ss_ones + 4'b1;
        end
    end
    
    assign add_ss_tens = end_ss_ones;
    assign end_ss_tens = add_ss_tens && (ss_tens == 4'd5);
    always @(posedge clk)begin
        if(reset)
            ss_tens <= 4'b0;
        else if(add_ss_tens)begin
            if(end_ss_tens)
                ss_tens <= 4'b0;
            else 
                ss_tens <= ss_tens + 4'b1;
        end
    end
    
    assign add_mm_ones = end_ss_tens;
    assign end_mm_ones = add_mm_ones && (mm_ones == 4'd9);
    always @(posedge clk)begin
        if(reset)
            mm_ones <= 4'b0;
        else if(add_mm_ones)begin
            if(end_mm_ones)
                mm_ones <= 4'b0;
            else
                mm_ones <= mm_ones + 4'b1;
        end
    end
    
    assign add_mm_tens = end_mm_ones;
    assign end_mm_tens = add_mm_tens && (mm_tens == 4'd5);
	always @(posedge clk)begin
        if(reset)
            mm_tens <= 4'b0;
        else if(add_mm_tens)begin
            if(end_mm_tens)
                mm_tens <= 4'b0;
            else 
                mm_tens <= mm_tens + 4'b1;
        end
    end
    
    assign add_hh_ones = end_mm_tens;
    assign end_hh_ones_0 = add_hh_ones && (hh_ones == 4'd9);
    assign end_hh_ones_1 = add_hh_ones && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
    always @(posedge clk)begin
        if(reset)
            hh_ones <= 4'd2;
        else if(add_hh_ones)begin
            if(end_hh_ones_0)
                hh_ones <= 4'b0;
            else if(end_hh_ones_1)
                hh_ones <= 4'b1;
            else 
                hh_ones <= hh_ones + 4'b1;
        end
    end

    assign add_hh_tens = end_mm_tens;
    assign end_hh_tens_0 = add_hh_tens && end_hh_ones_1;
    assign end_hh_tens_1 = add_hh_tens && end_hh_ones_0;
    always @(posedge clk)begin
        if(reset)
            hh_tens <= 4'b1;
        else if(add_hh_tens)begin
            if(end_hh_tens_0)
                hh_tens <= 4'b0;
            else if(end_hh_tens_1)
                hh_tens <= hh_tens + 4'b1;
        end
    end
    
    always@(posedge clk)begin
        if(reset)
            pm_temp <= 1'b0;
        else if(pm_ding)
            pm_temp <= ~pm_temp;
    end
    
    assign pm_ding = hh_tens == 4'd1 && hh_ones == 4'd1 && end_mm_tens;
    
    assign ss = {ss_tens, ss_ones};
    assign mm = {mm_tens, mm_ones};
    assign hh = {hh_tens, hh_ones};
    assign pm = pm_temp;
    
endmodule

验证结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考资料: Verilog计数器.

标签:reset,enable,clk,HDLBits,第十一章,练习,计数器,ones,input
来源: https://blog.csdn.net/weixin_44887565/article/details/120418450

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有