关注 望森FPGA 查看更多FPGA资讯
这是望森的第 13 期分享
作者 | 望森
来源 | 望森FPGA
目录
1 Four-bit binary counter | 四位二进制计数器
3 Decade counter again | 十进制计数器
4 Slow decade counter | 慢速十进制计数器
7 4-digit decimal counter | 4 位十进制计数器
本文中的代码都能够正常运行,请放心食用😋~
练习的官方网站是:https://hdlbits.01xz.net/
注:作者将每个练习的知识点都放在了题目和答案之后
1 Four-bit binary counter | 四位二进制计数器
题目:
构建一个 4 位二进制计数器,计数范围从 0 到 15(含 0 和 15),周期为 16。复位输入是同步的,应将计数器复位为 0。
答案:
我的答案:
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always@(posedge clk)begin
if (reset | q == 4'd15)begin
q <= 4'd0;
end
else begin
q <= q + 1;
end
end
endmodule
参考答案:
module top_module(
input clk,
input reset,
output reg [3:0] q);
always @(posedge clk)
if (reset)
q <= 0;
else
q <= q+1; // Because q is 4 bits, it rolls over from 15 -> 0.
// If you want a counter that counts a range different from 0 to (2^n)-1,
// then you need to add another rule to reset q to 0 when roll-over should occur.
endmodule
知识点:
相比我的答案,参考答案更简洁,因为4bit的q最大计数值就为15,可以利用这一点简化代码。
2 Decade counter | 十进制计数器
题目:
构建一个十进制计数器,计数范围从 0 到 9(含 0 和 9),周期为 10。复位输入是同步的,应将计数器复位为 0。
答案:
我的答案:
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always@(posedge clk)begin
if (reset | q == 4'd9)begin
q <= 4'd0;
end
else begin
q <= q + 1;
end
end
endmodule
参考答案:
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
知识点:
参考答案使用的 if 判断条件是“(reset || q == 9)”,此处使用了逻辑运算符“||”,更加严谨。
3 Decade counter again | 十进制计数器
题目:
制作一个十进制计数器,计数范围从 1 到 10(含 10)。复位输入是同步的,应将计数器复位为 1。
答案:
module top_module (
input clk,
input reset,
output [3:0] q);
always@(posedge clk)begin
if (reset | q == 4'd10)begin
q <= 4'd1;
end
else begin
q <= q + 1;
end
end
endmodule
4 Slow decade counter | 慢速十进制计数器
题目:
构建一个十进制计数器,计数范围从 0 到 9(含 0 和 9),周期为 10。重置输入是同步的,应将计数器重置为 0。我们希望能够暂停计数器,而不是始终在每个时钟周期递增,因此 slowena 输入指示计数器应何时递增。
答案:
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 if (slowena)begin
if (q == 4'd9)
q <= 4'd0;
else
q <= q + 1;
end
else begin
q <= q;
end
end
endmodule
5 Counter 1-12 | 计数器 1-12
题目:
设计一个具有以下输入和输出的 1-12 计数器:
-
Reset 同步高电平有效复位,将计数器复位为 1
-
Enable 设置为高电平以使计数器运行
-
Clk 正沿触发时钟输入
-
Q[3:0] 计数器的输出
-
c_enable、c_load、c_d[3:0] 控制信号进入提供的 4 位计数器,以便验证操作是否正确。
您有以下可用组件:
-
下面的 4 位二进制计数器 (count4),具有 Enable 和同步并行 load 输入(load的优先级高于 enable)。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 输入的信号。其目的是检查这些信号的正确性。
答案:
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(clk),
.enable(c_enable),
.load(c_load),
.d(c_d),
.Q(Q)
);
assign c_enable = enable;
assign c_load = reset | (Q == 4'd12 && enable);
assign c_d = c_load ? 1'b1 : 1'b0;
endmodule
知识点:
本题的意思是通过实例化已有的计数器模块,实现目标的计数器功能,因此,使用逻辑设计例化模块的控制信号即可。
6 Counter 1000 | 计数器 1000
题目:
从 1000 Hz 时钟中导出一个 1 Hz 信号,称为 OneHertz,该信号可用于驱动一组小时/分钟/秒计数器的启用信号,以创建数字挂钟。由于我们希望时钟每秒计数一次,因此 OneHertz 信号必须每秒精确地断言一个周期。使用模 10 (BCD) 计数器和尽可能少的其他门构建分频器。还要从您使用的每个 BCD 计数器输出启用信号(c_enable[0] 表示最快的计数器,c_enable[2] 表示最慢的计数器)。
为您提供以下 BCD 计数器。计数器 enable 必须启用高电平。reset 是同步的,设置为高电平以强制计数器归零。电路中的所有计数器必须直接使用相同的 1000 Hz 信号。
module bcdcount (
input clk,
input reset,
input enable,
output reg [3:0] Q
);
答案:
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
); //
wire [3:0] one,ten,hundred;
bcdcount counter0 (clk, reset, c_enable[0] , one);
bcdcount counter1 (clk, reset, c_enable[1] , ten);
bcdcount counter2 (clk, reset, c_enable[2] , hundred);
assign OneHertz = (hundred == 4'd9) && (ten == 4'd9) && (one == 4'd9);
assign c_enable[0] = 1'b1;
assign c_enable[1] = (one == 4'd9);
assign c_enable[2] = (ten == 4'd9) && (one == 4'd9);
endmodule
知识点:
信号声明时,注意信号位宽。
7 4-digit decimal counter | 4 位十进制计数器
题目:
构建一个 4 位 BCD(二进制编码的十进制)计数器。每个十进制数字使用 4 位进行编码:q[3:0] 为个位数字,q[7:4] 为十位数字,等等。对于数字 [3:1],还输出一个使能信号,指示何时应增加上三位数字。
您可能想要实例化或修改一些一位十进制计数器。
答案:
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q);
wire [3:0] one,ten,hundred,thousand;
assign ena[1] = (one == 4'd9);
assign ena[2] = (one == 4'd9) && (ten == 4'd9);
assign ena[3] = (one == 4'd9) && (ten == 4'd9) && (hundred == 4'd9);
assign q = {thousand,hundred,ten,one};
countBCD10 count_one(
.clk(clk),
.slowena(1'b1),
.reset(reset),
.q(one)
);
countBCD10 count_ten(
.clk(clk),
.slowena(ena[1]),
.reset(reset),
.q(ten)
);
countBCD10 count_hun(
.clk(clk),
.slowena(ena[2]),
.reset(reset),
.q(hundred)
);
countBCD10 count_thou(
.clk(clk),
.slowena(ena[3]),
.reset(reset),
.q(thousand)
);
endmodule
module countBCD10 (
input clk,
input slowena,
input reset,
output [3:0] q);
always@(posedge clk)begin
if (reset)begin
q <= 4'd0;
end
else if (slowena)begin
if (q == 4'd9)
q <= 4'd0;
else
q <= q + 1;
end
else begin
q <= q;
end
end
endmodule
8 12-hour clock | 12 小时制时钟
题目:
创建一组适合用作 12 小时时钟(带 am/pm 指示器)的计数器。计数器由快速运行的 clk 计时,每当您的时钟需要递增时(即每秒一次),ena 上都会发出脉冲。
reset 将时钟重置为 12:00 AM。pm 为 0 表示 AM,为 1 表示 PM。hh、mm 和 ss 分别是小时(01-12)、分钟(00-59)和秒(00-59)的两个 BCD(二进制编码十进制)数字。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。
答案:
我的答案:
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
//AM/PM
always@(posedge clk)begin
if (reset)
pm <= 1'b0;
else if (ena && (ss[7:4] == 4'd5 && ss[3:0] == 4'd9) && (mm[7:4] == 4'd5 && mm[3:0] == 4'd9)
&& (hh[7:4] == 4'd1 && hh[3:0] == 4'd1)) begin
pm <= ~pm;
end
end
//hour
always@(posedge clk)begin
if (reset)
hh[3:0] <= 4'd2;
else if (ena && (ss[7:4] == 4'd5 && ss[3:0] == 4'd9) && (mm[7:4] == 4'd5 && mm[3:0] == 4'd9)) begin
if (hh[7:4] == 4'd1 && hh[3:0] == 4'd2)
hh[3:0] <= 4'b1;
else if (hh[7:4] == 4'd0 && hh[3:0] == 4'd9)
hh[3:0] <= 4'b0;
else
hh[3:0] <= hh[3:0] + 1;
end
end
always@(posedge clk)begin
if (reset)
hh[7:4] <= 4'd1;
else if (ena && (ss[7:4] == 4'd5 && ss[3:0] == 4'd9) && (mm[7:4] == 4'd5 && mm[3:0] == 4'd9)) begin
if (hh[7:4] == 4'd0 && hh[3:0] == 4'd9)
hh[7:4] <= 4'b1;
else if (hh[7:4] == 4'd1 && hh[3:0] == 4'd2)
hh[7:4] <= 4'b0;
else
hh[7:4] <= hh[7:4];
end
end
//minute
always@(posedge clk)begin
if (reset)
mm[3:0] <= 4'b0;
else if (ena && (ss[7:4] == 4'd5 && ss[3:0] == 4'd9)) begin
if (mm[3:0] == 4'd9)
mm[3:0] <= 4'b0;
else
mm[3:0] <= mm[3:0] + 1;
end
end
always@(posedge clk)begin
if (reset)
mm[7:4] <= 4'b0;
else if (ena && (ss[7:4] == 4'd5 && ss[3:0] == 4'd9) && (mm[3:0] == 4'd9)) begin
if (mm[7:4] == 4'd5)
mm[7:4] <= 4'b0;
else
mm[7:4] <= mm[7:4] + 1;
end
end
//second
always@(posedge clk)begin
if (reset)
ss[3:0] <= 4'b0;
else if (ena) begin
if (ss[3:0] == 4'd9)
ss[3:0] <= 4'b0;
else
ss[3:0] <= ss[3:0] + 1;
end
end
always@(posedge clk)begin
if (reset)
ss[7:4] <= 4'b0;
else if (ena && ss[3:0] == 4'd9) begin
if (ss[7:4] == 4'd5 && ss[3:0] == 4'd9)
ss[7:4] <= 4'b0;
else
ss[7:4] <= ss[7:4] + 1;
end
end
endmodule
- END -
公z号/CSDN搜索【望森FPGA】,查看更多FPGA资讯~
相关推荐文章,点击跳转: