概述
写在前面
全部答案汇总:刷完这套题,我才发现Verilog原来如此简单----HDLBits答案汇总
今天更新Circuits章节中Sequential Logic的1个小节:Counters。
Four-bit binary counter
题目:构建一个从0到15的4位二进制计数器,周期为16。同步复位,复位应该将计数器重置为0。
个人思路:
因为这个题目是4位宽的计数器且要求从0-15计数,那么可以不要设置清零条件(计数器到15后会溢出自动到0),所以只要在复位无效的情况下,计数器输出每周期递增一;
复位有效时,计数器输出0。
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always@(posedge clk)begin
if(reset)
q <= 4'd0;
else
q <= q + 1'b1;
end
endmodule
Decade counter
题目:构建一个从0到9的4位二进制计数器,周期为10。同步复位,复位应该将计数器重置为0。
个人思路:
这个题目是4位宽的计数器且要求从0-9计数,和上题不同的是,计数器到9后即要求恢复到0,所以不存在溢出的情况,需要手动清零。所以当计数器计数到9,计数器清零,其他
时候计数器每周期递增一;复位有效时,计数器输出0。
module top_module (
input clk,
input reset,
output [3:0] q);
always@(posedge clk)begin
if(reset)
q <= 4'd0;
else if(q == 4'd9) //计数到最大值清零
q <= 4'd0;
else
q <= q + 1'b1; //其他时候每周期+1
end
endmodule
Decade counter again
题目:构建一个从1到10的4位二进制计数器。同步复位,复位应该将计数器重置为1。
个人思路:
和上题基本相同;只需要把复位重置为1,且从1-10计数(计数最大值为10)。
module top_module (
input clk,
input reset,
output [3:0] q);
always@(posedge clk)begin
if(reset)
q <= 4'd1;
else if(q == 4'd10)
q <= 4'd1;
else
q <= q + 1'b1;
end
endmodule
Slow decade counter
题目:构建一个从0到9(包括9)的十进制计数器,其周期为10。同步复位,复位应该将计数器重置为0。我们希望能够暂停计数器,而不是总是在每个时钟周期中递增,因此slowena
输入指示计数器应该何时递增。
个人思路:
计数器在递增时应判断使能slowena是否有效,有效则递增或清零(计数到最大值),无效则保持。
module top_module (
input clk,
input slowena,
input reset,
output [3:0] q);
always@(posedge clk)begin
if(reset)
q <= 4'd0;
else if(slowena)begin
if(q == 4'd9)
q <= 4'd0;
else
q <= q + 1'd1;
end
else
q <= q;
end
endmodule
Counter 1-12
题目:
使用以下条件设计一个1-12的计数器:
- Reset:高电平有效的同步复位信号,复位到1
- Enable:高电平有效的计数器计数使能信号
- Clk:上升沿触发的时钟输入
- Q[3:0]:计数器输出
- c_enable, c_load, c_d[3:0] 控制信号到提供的4位计数器,因此可以验证正确的操作。
您需要准备以下组件:
- 下面的4位二进制计数器(coun4),它具有使能和同步并行载入(载入优先级高于使能)。count4模块将提供给您。在你的电路中实例化它。
- 逻辑门
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输入的信号。它们的目的是为了检查这些信号的正确性。
个人思路:
题目提供了一个4位的计数器(0-15):
使能信号enable:直接把c_enable连到这里就可以
载入信号load:结合c_load可以实现复位清零,以及最大值清零
载入值c_load:同上
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'dx; //载入时载入值为1,其他时候不关心
count4 the_counter (clk, c_enable, c_load, c_d , Q);
endmodule
Counter 1000
题目:
从一个1000hz的时钟,派生一个1hz的信号,称为OneHertz,它可以用来驱动一组小时/分钟/秒计数器的启用信号,以创建一个数字挂钟。因为我们想让时钟每秒计数一次,所以一hz信号必须精确地保持每秒一个周期。建立分频器使用模10 (BCD)计数器和尽可能少的其他门。还输出您使用的每个BCD计数器的启用信号(c_enable[0]表示最快的计数器,c_enable[2]表示最慢的计数器)。
以下BCD模块将提供给您。Enable是高电平有效的计数器使能信号。Reset是高电平有效同步复位信号,复位值为0。电路中的所有计数器必须直接使用相同的1000hz信号。
module bcdcount ( input clk, input reset, input enable, output reg [3:0] Q );
个人思路:
从1000hz--1hz输出,实际上就是要设计一个周期为1000的计数器(每次计数到999就输出一个信号,这个信号周期就是1hz)。题目给出了一个4位的BCD模块,我们可以例化三次这个模块,第一次例化计数10次(每个时钟周期+1),第二次例化计数10次(在第一次例化每计数10次时加+1),第三次例化计数10次(在第二次例化每计数10次时加+1),这样就实现了每1000个时钟周期+1,对应的输出信号的频率也就变成了1hz。
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'b1};
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
4-digit decimal counter
题目:
构建一个4位BCD(二进制编码的十进制)计数器。每个十进制数字使用4位进行编码:q[3:0]是个位,q[7:4]是十位,以此类推。各进制上的进位时也需输出一个使能信号,指示三位数字何时应该增加。
个人思路:
千、百、十、个一共4位(每位4位宽,共16位宽),分别计数即可,设计的时候注意好计数使能条件和清零条件就好。细节看代码注释吧。
module top_module (
input clk,
input reset,
output [3:1] ena,
output [15:0] q
);
//个、十、百、千计数器
reg [3:0] ones;
reg [3:0] tens;
reg [3:0] hundreds;
reg [3:0] thousands;
//个、十、百、千计数器使能信号
wire ones_ena;
wire tens_ena;
wire hundreds_ena;
wire thousands_ena;
//个、十、百、千计数器清零信号
wire ones_end;
wire tens_end;
wire hundreds_end;
wire thousands_end;
//个、十、百、千计数器使能条件
assign ones_ena = 1'b1; //个计数器一直计数
assign tens_ena = ones_end; //十计数器在个计数器清零一次(计数到最大值)计数+1
assign hundreds_ena = tens_end; //百计数器在十计数器清零一次(计数到最大值)计数+1
assign thousands_ena = hundreds_end; //千计数器在百计数器清零一次(计数到最大值)计数+1
//个、十、百、千计数器清零条件
assign ones_end = (ones == 4'd9); //计数到最大值9清零
assign tens_end = (tens == 4'd9 && ones == 4'd9);//计数到最大值99清零
assign hundreds_end = (hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9);//计数到最大值999清零
assign thousands_end = (thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9);//计数到最大值9999清零
//个计数器计数always块
always@(posedge clk)begin
if(reset)
ones <= 4'd0;
else if(ones_end)
ones <= 4'd0;
else if(ones_ena)
ones <= ones + 1'b1;
end
//十计数器计数always块
always@(posedge clk)begin
if(reset)
tens <= 4'd0;
else if(tens_end)
tens <= 4'd0;
else if(tens_ena)
tens <= tens + 1'b1;
end
//百计数器计数always块
always@(posedge clk)begin
if(reset)
hundreds <= 4'd0;
else if(hundreds_end)
hundreds <= 4'd0;
else if(hundreds_ena)
hundreds <= hundreds + 1'b1;
end
//千计数器计数always块
always@(posedge clk)begin
if(reset)begin
thousands <= 4'd0;
end
else if(thousands_end)begin
thousands <= 4'd0;
end
else if(thousands_ena) begin
thousands <= thousands + 1'b1;
end
end
//输出
assign q = {thousands, hundreds, tens, ones}; //个、十、百、千拼接输出
assign ena[1] = (ones_end) ? 1'b1 : 1'b0;
assign ena[2] = (tens_end) ? 1'b1 : 1'b0;
assign ena[3] = (hundreds_end) ? 1'b1 : 1'b0;
endmodule
12-hour clock
题目:
创建一组适合作为12小时的时钟使用的计数器(带有am/pm指示器)。你的计数器是由一个快速运行的clk驱动,每次时钟增加时ena必须为1。reset将时钟重置到中午12点。上午时pm=0,下午时pm=1。hh,mm和ss分别是小时(01-12)、分钟(00-59)和秒(00-59)的两个BCD(二进制编码的十进制)数字。
Reset比enable具有更高的优先级,并且即使在没有启用时也会发生。
下面的时序图显示了从11:59:59 AM到12:00:00 PM的翻转行为以及同步的Reset和enable行为。
个人思路:
时、分、秒一共6位,分别计数即可,设计的时候注意好计数使能条件和清零条件就好。细节看代码注释吧。
module top_module(
input clk, //时钟
input reset, //复位
input ena, //计数使能信号
output pm, //pm标志,1:PM;0:AM
output [7:0] hh, //时BCD
output [7:0] mm, //分BCD
output [7:0] ss); //秒BCD
reg pm_temp; //pm寄存值
reg [3:0] ss_ones; //秒个位计数器
reg [3:0] ss_tens; //秒十位计数器
reg [3:0] mm_ones; //分个位计数器
reg [3:0] mm_tens; //分十位计数器
reg [3:0] hh_ones; //时个位计数器
reg [3:0] hh_tens; //时十位计数器
wire ss_ones_ena; //秒个位计数使能
wire ss_tens_ena; //秒十位计数使能
wire mm_ones_ena; //分个位计数使能
wire mm_tens_ena; //分十位计数使能
wire hh_ones_ena; //时个位计数使能
wire hh_tens_ena; //时十位计数使能
wire ss_ones_end; //秒个位计数完成
wire ss_tens_end; //秒个位计数完成
wire mm_ones_end; //分个位计数完成
wire mm_tens_end; //分十位计数完成
wire hh_ones_0_end; //时个位计数完成(十位为0)
wire hh_ones_1_end; //时个位计数完成(十位为1)
wire hh_tens_0_end; //时十位计数完成(十位为0)
wire hh_tens_1_end; //时十位计数完成(十位为1)
wire pm_inv; //PM跳转标志
//时、分、秒计数使能条件
assign ss_ones_ena = ena; //使能信号有效秒钟各位开始计数
assign ss_tens_ena = ss_ones_end; //秒钟个位计数完成后,秒钟十位开始计数
assign mm_ones_ena = ss_tens_end; //秒钟个位计数完成后,分钟个位开始计数
assign mm_tens_ena = mm_ones_end; //分钟个位计数完成后,秒钟十位开始计数
assign hh_ones_ena = mm_tens_end; //分钟十位计数完成后,时钟个位开始计数
assign hh_tens_ena = mm_tens_end; //时钟个位计数完成后,时钟十位开始计数
//时、分、秒计数完成判断
assign ss_ones_end = ss_ones_ena && (ss_ones == 4'd9); //秒钟个位计数使能信号有效,且秒钟个位计数到最大值9
assign ss_tens_end = ss_tens_ena && (ss_tens == 4'd5); //秒钟十位计数使能信号有效,且秒钟十位计数到最大值5
assign mm_ones_end = mm_ones_ena && (mm_ones == 4'd9); //时钟个位计数使能信号有效,且时钟个位计数到最大值9
assign mm_tens_end = mm_tens_ena && (mm_tens == 4'd5); //时钟十位计数使能信号有效,且时钟十位计数到最大值5
//时钟个位计数使能信号有效,且时钟个位计数到最大值9(十位为0)
assign hh_ones_0_end = hh_ones_ena && ((hh_ones == 4'd9) && (hh_tens == 4'd0));
//时钟个位计数使能信号有效,且时钟个位计数到最大值2(十位为1)
assign hh_ones_1_end = hh_ones_ena && ((hh_ones == 4'd2) && (hh_tens == 4'd1));
assign hh_tens_0_end = hh_tens_ena && hh_ones_1_end; //时钟十位计数使能信号有效,且时钟个位计数完成(十位为0)
assign hh_tens_1_end = hh_tens_ena && hh_ones_0_end; //时钟十位计数使能信号有效,且时钟个位计数完成(十位为1)
//pm跳转条件判断
assign pm_inv = hh_tens == 4'd1 && hh_ones == 4'd1 && mm_tens_end;
//pm标志位输出
assign pm = pm_temp;
//时、分、秒输出
assign ss = {ss_tens, ss_ones}; //十位、个位拼接
assign mm = {mm_tens, mm_ones}; //十位、个位拼接
assign hh = {hh_tens, hh_ones}; //十位、个位拼接
//秒钟的个位计数
always @(posedge clk)begin
if(reset)begin
ss_ones <= 4'b0; //复位清零
end
else if(ss_ones_ena)begin //使能有效
if(ss_ones_end)begin //计数完成则清零
ss_ones <= 4'b0;
end
else begin
ss_ones <= ss_ones + 4'b1; //计数递加1
end
end
end
//秒钟的十位计数
always @(posedge clk)begin
if(reset)begin
ss_tens <= 4'b0;
end
else if(ss_tens_ena)begin
if(ss_tens_end)begin
ss_tens <= 4'b0;
end
else begin
ss_tens <= ss_tens + 4'b1;
end
end
end
//分钟的个位计数
always @(posedge clk)begin
if(reset)begin
mm_ones <= 4'b0;
end
else if(mm_ones_ena)begin
if(mm_ones_end)begin
mm_ones <= 4'b0;
end
else begin
mm_ones <= mm_ones + 4'b1;
end
end
end
//分钟的十位计数
always @(posedge clk)begin
if(reset)begin
mm_tens <= 4'b0;
end
else if(mm_tens_ena)begin
if(mm_tens_end)begin
mm_tens <= 4'b0;
end
else begin
mm_tens <= mm_tens + 4'b1;
end
end
end
//时钟的个位计数
always @(posedge clk)begin
if(reset)begin
hh_ones <= 4'd2;
end
else if(hh_ones_ena)begin
if(hh_ones_0_end)begin
hh_ones <= 4'b0;
end
else if(hh_ones_1_end)begin
hh_ones <= 4'b1;
end
else begin
hh_ones <= hh_ones+4'b1;
end
end
end
//时钟的十位计数
always @(posedge clk)begin
if(reset)begin
hh_tens <= 4'b1;
end
else if(hh_tens_ena)begin
if(hh_tens_0_end)begin
hh_tens <= 4'b0;
end
else if(hh_tens_1_end)begin
hh_tens <= hh_tens + 4'b1;
end
end
end
//pm跳转
always@(posedge clk)begin
if(reset)begin
pm_temp <= 1'b0;
end
else if(pm_inv)begin //满足跳转条件则翻转
pm_temp <= ~pm_temp;
end
end
endmodule
最后
以上就是轻松玫瑰为你收集整理的刷完这套题,我才发现Verilog原来如此简单----HDLBits答案系列---- Counters写在前面Four-bit binary counterDecade counterDecade counter againSlow decade counterCounter 1-12Counter 10004-digit decimal counter12-hour clock的全部内容,希望文章能够帮你解决刷完这套题,我才发现Verilog原来如此简单----HDLBits答案系列---- Counters写在前面Four-bit binary counterDecade counterDecade counter againSlow decade counterCounter 1-12Counter 10004-digit decimal counter12-hour clock所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复