我是靠谱客的博主 机灵云朵,最近开发中收集的这篇文章主要介绍HDLBits-Circuits学习小结(五)计数器(counters)1 简单的计数器2 较为复杂的计数器,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 1 简单的计数器
    • 1.1 二进制、十进制计数器
    • 1.2 可以暂停的计数器
  • 2 较为复杂的计数器
    • 2.1 从1计数到12的计数器
    • 2.2 从1000Hz时钟中导出1Hz的信号
    • 2.3 构建4位BCD计数器
    • 2.4 创建12小时时钟的计数器

1 简单的计数器

1.1 二进制、十进制计数器

构建一个4位二进制计数器,其计数范围从0到15(包括0和15),周期为16。置位输入是同步的,应该将计数器重置为0。

count15
solution:

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

构建一个十进制计数器,其计数范围从0到9(包括0和9),周期为10。置位输入是同步的,应该将计数器重置为0。
十进制计数器
solution:

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

endmodule

official solution:

module top_module(
	input clk,
	input reset,
	output reg [3:0] q);
	
	always @(posedge clk)
		if (reset || q == 9)	// Count to 10 requires rolling over 9->0 instead of the more natural 15->0
			q <= 0;
		else
			q <= q+1;
	
endmodule

做一个十进制计数器,计数范围为1到10(含1和10)。复位输入是同步的,应将计数器复位为1。

count1to10
solution:

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

1.2 可以暂停的计数器

构建一个十进制计数器,其计数范围从0到9(包括0和9),周期为10。置位输入是同步的,应该将计数器重置为0。
我们希望能够暂停计数器,而不是总是每个时钟周期递增,因此slowena输入指出计数器应该何时递增。

slowena
错误的solution:

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

endmodule

原因在于这里的slowena是控制计数器递增的,即使是计数器是9,如果slowena没有发出递增的指令,那么计数器将保持是9。

正确的solution:

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

endmodule

2 较为复杂的计数器

2.1 从1计数到12的计数器

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

可以使用以下组件:

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

solution:

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, c_enable, c_load, c_d , Q);
    assign c_enable = enable; 
    assign c_load = reset | (Q == 12 & enable ==1);
    assign c_d = 1'b1;
    
endmodule

2.2 从1000Hz时钟中导出1Hz的信号

????

从一个1000 Hz的时钟中,导出一个称为OneHertz的1 Hz信号,该信号可用于为一组小时/分钟/秒计数器驱动启用信号,以创建数字挂钟。由于我们希望时钟每秒计数一次,因此必须在每秒精确的一个周期内确定OneHertz信号。使用模数模块构建分频器。

使用modulo-10 (BCD)计数器和尽可能少的逻辑门来构建分频器。还输出使用的每个BCD计数器的enable信号(c_enable[0]表示最快的计数器,c_enable[2]表示最慢的计数器)。

给定下面的BCD计数器。使能端enable必须为高电平才能使计数器运行。复位是同步的,并设置为高电平时迫使计数器为零。电路中的所有计数器必须直接使用相同的1000Hz信号。

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

这是一道难题,思考过程参考的是这篇文章,这篇文章中提到:

如何设计这样一个电路呢?

通过例化一个10进制bcd码计数器,来实现1000分频的分频器。

也就是说时钟是1Khz的时钟,如何通过计数得到一个1Hz的信号,持续一个时钟就行。

那就计数到999给一个输出作为1Hz信号输出。

如何实现计数到999呢?

由于给的是一个模10计数器,所以先例化一个个位计数器,技术到9,给十位计数器一个使能,让其计数,同理,十位计数器计数到9给百位计数器一个使能,就可以得到这样的一个计数器。

从时间的角度上看,1khz就是0.001s,而1hz就是1s,那么这样就就可以解释通了。

solution:

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

    wire [3:0] q0,q1,q2; //一定要注明输出的长度,这里和bcdcount保持一致
    assign c_enable = {q1==4'd9 & q0==4'd9,q0==4'd9,1'b1};
    assign OneHertz = {q2==4'd9 & q1==4'd9 & q0==4'd9};
    
    bcdcount count0 (clk,reset,c_enable[0],q0);
    bcdcount count1 (clk,reset,c_enable[1],q1);
    bcdcount count2 (clk,reset,c_enable[2],q2);
    
endmodule

2.3 构建4位BCD计数器

构建一个4位BCD(二进制编码的十进制)计数器。每一位十进制数字都用4位编码:q[3:0]是个位,q[7:4]是十位,等等。对于数字位[3:1],还输出一个enable信号,指示高三位数字中的每一位何时应该递增。
您可能要实例化或修改一些一位十进制计数器。

BCD

module top_module (
    input clk,
    input reset,   // Synchronous active-high reset
    output [3:1] ena,
    output [15:0] q);
    
    wire enable;
    assign enable = 1'b1;
    assign ena = {q[3:0]==4'd9 & q[7:4]==4'd9 & q[11:8]==4'd9,q[3:0]==4'd9 & q[7:4]==4'd9,q[3:0]==4'd9};
    bcd bcd0 (clk,reset,enable,q[3:0]);
    bcd bcd1 (clk,reset,ena[1],q[7:4]);
    bcd bcd2 (clk,reset,ena[2],q[11:8]);
    bcd bcd3 (clk,reset,ena[3],q[15:12]);

endmodule

module bcd(
	input clk,
	input reset,
    input ena,
	output reg [3:0] q);
	
    always @(posedge clk) begin
        if (reset)	// Count to 10 requires rolling over 9->0 instead of the more natural 15->0
			q <= 0;
    	else if (ena) begin
        	if (q < 9)
            	q <= q + 1;
        	else
            	q <= 0;
    	end
        else
            q <= q;
    end
	
endmodule

2.4 创建12小时时钟的计数器

创建一组适合用作12小时时钟的计数器(带有am / pm指示器)。您的计数器由快速运行的时钟提供时钟,每当您的时钟增加(即每秒一次)时,便会在ena上产生一个脉冲。

重置将时钟重置为12:00 AM。 pm对于AM是0,对于PM是1。 hh,mm和ss是两个BCD(二进制-编码的十进制数字分别代表小时(01-12),分钟(00-59)和秒(00-59)。Reset的优先级比enable的优先级高。

以下时序图显示了从11:59:59 AM到12:00:00 PM的过渡行为以及同步复位和启用行为。

12小时
请注意,11:59:59 PM前进至12:00:00 AM,12:59:59 PM前进至01:00:00 PM。没有00:00:00。从图中知道,hh、mm、ss都是8位二进制数,且分为前四位和后四位,如果前四位满足了要求,后四位就加一个数;8位都满足了要求,就复位。

module top_module(
    input clk,
    input reset,
    input ena,
    output pm,
    output [7:0] hh,
    output [7:0] mm,
    output [7:0] ss); 
    
    wire [3:0] enable;
    assign enable[0] = ena;
    assign enable[1] = ena & (ss==8'h59);
    assign enable[2] = ena & (ss==8'h59) & (mm==8'h59);
    assign enable[3] = ena & (hh==8'h11) & (ss==8'h59) & (mm==8'h59);
    
    count60 second  (clk,reset,enable[0],ss);
    count60 minute  (clk,reset,enable[1],mm);
    count12 hour    (clk,reset,enable[2],hh);
    count2  halfday (clk,reset,enable[3],pm);
    
endmodule

module count12(
    input clk,
    input reset,
    input ena,
    output [7:0] q);
    
    always @(posedge clk) begin
        if (reset)
            q <= 8'h12;
        else if (ena) begin
            if (q == 8'h12)
                q <= 8'h1;
            else if (q[3:0] == 4'h9) begin
                q[3:0] <= 0;
                q[7:4] <= 1;
            end
            else
                q[3:0] <= q[3:0] + 1;
        end
        else
            q <= q;
    end
    
endmodule
    
module count60(
    input clk,
    input reset,
    input ena,
    output [7:0] q);
    
    always @(posedge clk) begin
        if (reset)
            q <= 0;
        else if (ena) begin
            if (q == 8'h59)
                q <= 0;
            else if (q[3:0] == 4'h9) begin
                q[3:0] <= 0;
                q[7:4] <= q[7:4] + 1;
            end
            else
                q[3:0] <= q[3:0] + 1;
        end
        else
            q <= q;
    end
    
endmodule

module count2(
    input clk,
    input reset,
    input ena,
    output q);
    
    always @(posedge clk) begin
        if (reset)
            q <= 0;
        else if (ena) begin
            if (q < 1'b1)
                q <= q + 1;
            else
                q <= 0;
        end
        else
            q <= q;
    end
    
endmodule

最后

以上就是机灵云朵为你收集整理的HDLBits-Circuits学习小结(五)计数器(counters)1 简单的计数器2 较为复杂的计数器的全部内容,希望文章能够帮你解决HDLBits-Circuits学习小结(五)计数器(counters)1 简单的计数器2 较为复杂的计数器所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部