HDLbits 刷题答案 3.2.2 Counters

3.2.2 Counters

3.2.2.1 Count15

创建一个计数器,当同步复位信号reset1时,清零
在这里插入图片描述

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

3.2.2.2 Decade counter
模10计数器
在这里插入图片描述

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

3.2.2.3 Decade counter again
从1-10计数
在这里插入图片描述

module top_module (
    input clk,
    input reset,
    output [3:0] q);
	
    always @ (posedge clk) begin
        if(reset) begin
           q <= 4'd1; 
        end
        else begin
            if(q == 4'd10) begin
           		q <= 4'd1;
            end
            else begin
               q <= q + 1;
            end
        end
    end
endmodule

3.2.2.3 Slow decade counter
带使能端和复位端的模10计数器
在这里插入图片描述

module top_module (
    input clk,
    input slowena,
    input reset,
    output [3:0] q);
	
    always @ (posedge clk) begin
        if(reset) begin
           q <= 4'd0; 
        end 
        else begin
            if(slowena) begin
                if(q == 4'd9) begin
                   q <= 4'd0; 
                end
                else begin
               		q <= q + 1;
                end
            end
            else begin
               q <= q; 
            end
        end
    end
endmodule

3.2.2.4 Counter1-12

根据以下输入输出信号设计一个计算1~12的计数器

Reset:同步复位信号,高复位,将计数器复位为1.

Enable:使能信号高有效

Clk:时钟上升沿触发计数器工作

Q[3:0]:计数器输出

c_enable, c_load, c_d[3:0]:题目中给我们提供了一个4-bit的计数器,这三个信号是用于该4-bit计数器的控制信号。

题目提供给我们4-bit计数器

有enable信号,带复位和置位的计数器,将该计数器例化至我们的代码中。
再用一些其他的逻辑门来完成本题
在这里插入图片描述

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'd1 : 4'd0;
    count4 the_counter (.clk(clk), .enable(c_enable), .load(c_load), .d(c_d), .Q(Q)/*, ... */ );
endmodule

这个我没看懂,从网上找的代码

3.2.2.5 Counter1000

用4bit的BCD码实现个、十、百的计数,当计数1000次后,OneHertz输出为1
通过例化如下module实现该功能
在这里插入图片描述
当个位计数10次,十位计数1次
当十位计数10次,百位计数1次

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 = (hundred == 4'd9 && ten == 4'd9 && one == 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.2.2.6 4-digital decimal counter

同步复位信号
ena[3:0]代表进位输出信号
q16-bit数据输出,用BCD的形式表示

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 //one
        if(reset) begin
           	one <= 4'd0; 
        end
        else if(one == 4'd9) begin //one couter to 9, set one to 0
           	one <= 4'd0; 
        end	
        else begin
         	one <= one + 1'b1;
        end
    end

    always @ (posedge clk) begin	//ten
        if(reset) begin
           	ten <= 4'd0; 
        end
        else if(ten == 4'd9 && one == 4'd9) begin //one counter to 99, set ten to 0
           	ten <= 4'd0; 
        end
        else if(one == 4'd9) begin //one counter to 9, ten count one time
           	ten <= ten + 1'b1; 
        end
    end
    
    always @ (posedge clk) begin //hundred
        if(reset) begin
           	hundred <= 4'd0; 
        end
        else if(hundred == 4'd9 && ten == 4'd9 && one == 4'd9) begin //one counter to 999, set hundred to 0
           	hundred <= 4'd0; 
        end
        else if(ten == 4'd9 && one == 4'd9) begin//one counter to 99, hundred counter one time
           	hundred <= hundred + 1'b1; 
        end
    end
    
    always @ (posedge clk) begin //thousand
        if(reset) begin
           	thousand <= 4'd0; 
        end
        else if(thousand == 4'd9 && hundred == 4'd9 && ten == 4'd9 && one == 4'd9) begin
           	thousand <= 4'd0; //one counter to 9999, set thousand to 0
        end
        else if(hundred == 4'd9 && ten == 4'd9 && one == 4'd9) begin
            	thousand <= thousand + 1'b1; // one counter to 999, thousand counter one time
    	end
    end
    
    assign q = {thousand, hundred, ten, one};
    assign ena = {(hundred == 4'd9 && ten == 4'd9 && one == 4'd9), (ten == 4'd9 && one == 4'd9), (one == 4'd9)};
endmodule

总的来说,就是设计一个从0能计数到9999的计数器,从代码中可以看出,我用来4个always块来计数,分别代表个位、十位、百位和千位,在onealways块中,当one计数到9,就将one清零,在tenalways块中,当oneten都计数到9时,将其清零;在one计数到9时,ten才计数一次,同理,hundredthousand都是如此计数的,最后,将千位、百位、十位和个位,用连续赋值语句assign传递给q,对于进位输出信号ena,我也用连续赋值语句assign进行赋值,当one9的时候,ena[1]条件为真,输出为1,同理,ena[2]ena[3]处理方法类似

3.2.2.7 12-hour clock

创建一个带PM和AM的12小时制的时钟,要求

  • reset时,时间为12:00:00 AM
  • ena有效时候,开始计时
  • pm=0是AM,pm=1是PM
  • 11:59:59AM,下一时刻12: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 [3:0] hh_one;
    reg [3:0] hh_ten;
    reg [3:0] mm_one;
    reg [3:0] mm_ten;
    reg [3:0] ss_one;
    reg [3:0] ss_ten;
    
    reg pm_tmp;
      
    wire en_ss_one;
    wire end_ss_one;
    wire en_ss_ten;
    wire end_ss_ten;
    
    wire en_mm_one;
    wire end_mm_one;
    wire en_mm_ten;
    wire end_mm_ten;
    
    wire en_hh_one;
    wire end_hh_one_0;
    wire end_hh_one_1;
    
    wire en_hh_ten;
    wire end_hh_ten_0;
    wire end_hh_ten_1;
    
    wire pm_tmp_ping;
    
    /*		秒针的个位,计数到9,清零	*/
    assign en_ss_one = ena;
    assign end_ss_one = en_ss_one && (ss_one == 4'd9);
    
    always @ (posedge clk) begin
        if(reset) begin
           	 ss_one <= 4'd0;
        end
        else begin
            if(end_ss_one) begin
            	ss_one <= 4'd0;
            end
            else if(en_ss_one) begin
               	ss_one <= ss_one + 4'd1; 
            end
        end
    end
    
    /*		秒针的十位,个位计数到9,十位计数一次,秒针计数到59,清零	*/
    assign en_ss_ten = end_ss_one;	//--:--:-9
    assign end_ss_ten = en_ss_ten && (ss_ten == 4'd5);
    
    always @ (posedge clk) begin
        if(reset) begin
           	ss_ten <= 4'd0; 
        end
        else begin
            if(end_ss_ten) begin
               	ss_ten <= 4'd0; 
            end
            else if(en_ss_ten) begin
               	ss_ten <= ss_ten + 4'd1; 
            end
        end
    end

    /*		分针的个位,当秒针计数到59,分针个位计数一次	*/
    assign en_mm_one = end_ss_ten;	//--:--:59
    assign end_mm_one = en_mm_one && (mm_one == 4'd9);
    
    always @ (posedge clk) begin
        if(reset) begin
           	mm_one <= 4'd0; 
        end
        else begin
            if(end_mm_one) begin
               	mm_one <= 4'd0; 
            end
            else if(en_mm_one) begin
               	mm_one <= mm_one + 4'd1; 
            end
        end
    end
    
    /*	分针的十位,当秒针计数到59,分针计数到59,清零	*/
   	assign en_mm_ten = end_mm_one;	//--:-9:59
    assign end_mm_ten = en_mm_ten && (mm_ten == 4'd5);
    
    always @ (posedge clk) begin
        if(reset) begin
           	mm_ten <= 4'd0; 
        end
        else begin
            if(end_mm_ten) begin
               	mm_ten <= 4'd0; 
            end
            else if(en_mm_ten) begin
               	mm_ten <= mm_ten + 4'd1; 
            end
        end
    end
    
    /*	时针的个位,分两种情况,当时针的十位为0,可计数到9	*/
    /*	当时针的十位为1时,个位只能计数到2	*/
    assign en_hh_one = end_mm_ten;	// --:59:59
    assign end_hh_one_0 = en_hh_one && (hh_one == 4'd9);	//十位为0 -9:59:59
    assign end_hh_one_1 = en_hh_one && (hh_one == 4'd2 && hh_ten == 4'd1);	//十位为1 -2:59:59
    
    always @ (posedge clk) begin
        if(reset) begin
           	hh_one <= 4'd2; 
        end
        else begin
            if(end_hh_one_0) begin
                hh_one <= 4'd0;
            end
            else if(end_hh_one_1) begin
                hh_one <= 4'd1;
            end
            else if(en_hh_one) begin
                hh_one <= hh_one + 4'd1;
            end
        end
    end
    
    /*	时针的十位	*/
    assign en_hh_ten = end_mm_ten;
    assign end_hh_ten_0 = end_mm_ten && (hh_one == 4'd9); //09:59:59
    assign end_hh_ten_1 = end_mm_ten && (hh_one == 4'd2) && (hh_ten == 4'd1); //12:59:59
    
    always @ (posedge clk) begin
        if(reset) begin
           	hh_ten <= 4'd1; 
        end
        else if(en_hh_ten) begin
            if(end_hh_ten_0) begin
               	hh_ten <=  hh_ten + 4'd1;
            end
            else if(end_hh_ten_1) begin
                hh_ten <= 4'd0;
            end
        end
    end
    
    /*	PM 当11:59:59时,pm_tmp发生翻转	*/
    assign pm_tmp_ping = (hh_ten == 4'd1) && (hh_one == 4'd1) && end_mm_ten;
    
    always @ (posedge clk) begin
        if(reset) begin
           	pm_tmp <= 1'b0; 
        end
        else if(pm_tmp_ping) begin
           	pm_tmp <= ~pm_tmp; 
        end
    end
    
    assign ss = {ss_ten,ss_one};
    assign mm = {mm_ten,mm_one};
    assign hh = {hh_ten,hh_one};
    assign pm = pm_tmp;
endmodule
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值