HDLBITS笔记28:计数器综合题(较难)(包括1-12计数器、1000hz信号计数器、4位BCD计数器计数时钟(12-hour clock))

目录

题目1:counter 1-12

题目2:counter 1000

题目3:4-digit decimal counter(4位BCD计数器)

题目4:计数时钟(12-hour clock)


题目1:counter 1-12

设计具有以下输入和输出的 1-12 计数器:

  • Reset同步高电平有效复位,强制计数器为 1
  • Enable 设置为高电平以使计数器运行
  • Clk正边沿触发时钟输入
  • Q[3:0]计数器的输出
  • c_enable、c_load、c_d[3:0]控制信号进入提供的4位计数器,因此可以验证正确的操作。

您有以下可用的组件:

  • 下面的 4 位二进制计数器 (count4),它具有使能和同步并行加载输入(负载的优先级高于使能)。count4 模块已提供给您。在电路中实例化它。
  • 逻辑门
module count4(
	input clk,
	input enable,
	input load,
	input [3:0] d,
	output reg [3:0] Q
);

c_enablec_loadc_d输出分别是进入内部计数器使负载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
); 

   // count4 the_counter (.clk(clk), .(c_enable), .c_load, .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 u1(.clk(clk),.enable(c_enable),.load(c_load),.d(c_d),.Q(Q));

endmodule

仿真部分如下:

题目2:counter 1000

从 1000 Hz 时钟派生一个 1 Hz 信号(称为 OneHertz),该信号可用于驱动一组小时/分钟/秒计数器的 Enable 信号,以创建数字挂钟。由于我们希望时钟每秒计数一次,因此必须每秒精确地置位一个周期的一赫兹信号。使用模 10 (BCD) 计数器和尽可能少的其他门构建分频器。同时输出来自您使用的每个BCD计数器的使能信号(c_enable[0]表示最快的计数器,c_enable[2]表示最慢的计数器)。

为您提供以下BCD计数器。Enable必须为高电平,计数器才能运行。Reset是同步的,并设置为高电平以强制计数器为零。电路中的所有计数器必须直接使用相同的 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
); 

代码编写如下:

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

仿真结果如下:

 题目3:4-digit decimal counter(4位BCD计数器)

构建一个 4 位数的 BCD(二进制编码的十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是1位,q[7:4]是十位,依此类推。对于数字 [3:1],还要输出一个使能信号,指示上三位数字中的每一位何时应递增。

您可能希望实例化或修改一些一位数的十计数器

模块声明

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

代码编写如下:其中one、ten、hundred、thousand分别表示从最低位到最高位。

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

部分仿真结果如下:

题目4:计数时钟(12-hour clock)

创建一组适合用作 12 小时制的计数器(带 am/pm 指示器)。您的计数器由快速运行的clk计时,只要您的时钟应该增加(即每秒一次),就会在ena上发出脉冲。

Reset将时钟重置为 12:00 AM。pm 表示 AM 为 0,PM 为 1。hh、mm 和 ss 是两个 BCD(二进制编码十进制)数字,分别表示小时 (01-12)、分钟 (00-59) 和秒 (00-59)。Reset的优先级高于enable,即使未enable,也可能发生Reset

以下时序图显示了从上午 11:59:59 到中午 12:00:00 的翻转行为以及同步复位和使能行为。

模块声明

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

分析:

  • 制作的是一个12小时制的计数器,要求使用BCD计数器来实现
  • 要求有时分秒。
  • 有复位信号,且复位的优先级高于使能端,复位信号有效时能复位到12点,其中pm 表示 AM 为 0,PM 为 1。
  • 要求实现的时间是1点到12点。

代码:

//在顶层模块中实现例化
module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    count60 u1(.clk(clk),.reset(reset),.en(ena),.cnt_out(ss));//秒
    count60 u2(.clk(clk),.reset(reset),.en(ena&(ss==8'h59)),.cnt_out(mm));//分
    count12 u3(.clk(clk),.reset(reset),.en(ena&(ss==8'h59)&(mm===8'h59)),.cnt_out(hh));//时
    reg pm1;
    always @(posedge clk)
        begin
            if(reset)
                pm1 <= 8'h0;
            else if((hh == 8'h11)&(ss == 8'h59)&(mm == 8'h59))
                pm1 <= ~pm1;
            else;
        end
    assign pm =pm1;
endmodule
//设计0-59的模60计数器
module count60(clk,reset,en,cnt_out);
    input clk,reset,en;
    output reg [7:0] cnt_out;
    always @(posedge clk)
        begin
            if(reset)
                cnt_out <= 8'h0;
            else if(en)
                if(cnt_out == 8'h59)begin
                    cnt_out <= 8'h0;
                end
            else if(cnt_out[3:0] == 9)begin
                cnt_out[3:0] <= 0;
                cnt_out[7:4] <= cnt_out[7:4] + 1;//bcd计数器实现的递增
            end
            else
                
                cnt_out[3:0] <= cnt_out[3:0] + 1;

        end
endmodule
//设计模12的计数器
module count12(clk,en,reset,cnt_out);
    input clk,en,reset;
    output cnt_out;
    reg [7:0] cnt_out;
    always @(posedge clk)
        begin
            if(reset)
                cnt_out <= 8'h12;//题意要求复位有效时复位至12点
            else if(en)
                begin
                    if(cnt_out == 8'h12)
                        begin
                            cnt_out <= 1;
                        end
                    else if(cnt_out[3:0] == 9)
                        begin
                       cnt_out[3:0] <= 0;
                       cnt_out[7:4] <= cnt_out[7:4] + 1;//bcd计数器实现的递增
			            end
                    else
                        begin
                            cnt_out[3:0] <= cnt_out[3:0] + 1;
                        end
                end
        end
endmodule

仿真结果如下:

 使用quartus ii画出逻辑图如下:

 count60(模60计数器)

 count2模12计数器:

 题目4 代码参考:HDLBits 系列(19) 12小时时钟的Verilog设计_李锐博恩的博客-CSDN博客

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值