赞
踩
全部答案汇总:刷完这套题,我才发现Verilog原来如此简单----HDLBits答案汇总
今天更新Circuits章节中Sequential Logic的1个小节:Counters。
题目:构建一个从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
题目:构建一个从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
题目:构建一个从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
题目:构建一个从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
题目:
使用以下条件设计一个1-12的计数器:
您需要准备以下组件:
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
题目:
从一个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位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小时的时钟使用的计数器(带有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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。