概述
目录
- 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。
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。
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输入指出计数器应该何时递增。
错误的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信号,指示高三位数字中的每一位何时应该递增。
您可能要实例化或修改一些一位十进制计数器。
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的过渡行为以及同步复位和启用行为。
请注意,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 较为复杂的计数器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复