Four-bit binary counter
Solution
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always @(posedge clk) begin
if(reset == 1)
q <= 4'b0000;
else if(q == 4'b1111)
q <= 4'b0000;
else
q <= q + 1;
end
endmodule
Decade counter
Solution
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:0] q);
always @(posedge clk) begin
if(reset == 1)
q <= 4'b0000;
else if(q == 4'b1001)
q <= 4'b0000;
else
q <= q + 1;
end
endmodule
Decade counter again
Solution
module top_module (
input clk,
input reset,
output [3:0] q);
always @(posedge clk) begin
if(reset == 1)
q <= 4'b0001;
else if(q == 4'b1010)
q <= 4'b0001;
else
q <= q + 1;
end
endmodule
Slow decade counter
暂停功能:仅当 slowena
为高电平时,计数器才会在时钟上升沿递增;否则保持当前值。
Solution
module top_module (
input clk,
input slowena,
input reset,
output [3:0] q);
always @(posedge clk) begin
if(reset == 1)
q <= 4'd0;
else if(slowena) begin
if(q == 4'd9)
q <= 4'd0;
else
q = q + 1;
end else
q <= q;
end
endmodule
Counter 1-12
同步复位:reset
高电平时,时钟上升沿将计数器同步复位到 1。
使能控制:enable
高电平时,计数器运行(计数);enable
低电平时,计数器保持当前值(暂停)。
**load
的核心作用:
- **立即覆盖当前值**:当 `load=1` 时,无论计数器当前状态如何,都会在下一个时钟上升沿将 `d` 端口的值加载到计数器输出 `Q`。
- **优先级高于 `enable`**:即使 `enable=0`(计数器暂停),只要 `load=1`,计数器仍会加载 `d` 的值。
计数器的四种状态:
load | enable | 计数器行为 |
---|---|---|
1 | X | 加载 d 的值(例如复位到 1 或回绕到 1) |
0 | 1 | 正常计数(Q = Q + 1) |
0 | 0 | 保持当前值(暂停) |
1 | 0 | 仍加载 d 的值(load 优先级更高) |
已知:
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
);
assign c_enable = enable;
assign c_load = reset | (Q == 4'd12 && enable);
assign c_d = c_load ? 4'b1 : 4'b0;
count4 the_counter (
.clk(clk),
.enable(c_enable),
.load(c_load),
.d(c_d),
.Q(Q)
);
endmodule
Counter 1000
题中给出了一个十进制的模块,所以需要使用三次以达到把1000Hz降到1Hz.
已知:
module bcdcount (
input clk,
input reset,
input enable,
output reg [3:0] Q
);
Solution
module top_module (
input clk,
input reset,
output OneHertz,
output [2:0] c_enable
);
wire [3:0] one, ten, hundred;
// 实例化三个 bcdcount 模块,分别表示个位、十位、百位
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 c_enable[0] = 1'b1; // 个位始终使能(持续计数)
assign c_enable[1] = (one == 4'd9); // 十位仅在个位达到9时使能
assign c_enable[2] = (ten == 4'd9) && (one == 4'd9); // 百位仅在个位和十位都为9时使能
// 生成1Hz脉冲:当且仅当计数器达到999时,OneHertz输出高电平
assign OneHertz = (hundred == 4'd9) && (ten == 4'd9) && (one == 4'd9);
endmodule
4-digit decimal counter
题目要求:
构建一个 4 位 BCD(二进制编码十进制)计数器
位分配:每个十进制位用 4 位二进制编码:
q[3:0]
→ 个位(0~9),q[7:4]
→ 十位(0~9),q[11:8]
→ 百位(0~9),q[15:12]
→ 千位(0~9)(共 4 位,构成 0000~9999 的循环)。
- 使能信号:对于 十位、百位、千位(即高位的三位),需输出对应的使能信号(如
ena[1]
对应十位、ena[2]
对应百位、ena[3]
对应千位),指示该高位何时应递增(例如:个位计满 9 时,触发十位的使能信号)。 - 实现方式:可通过 实例化或修改 1 位十进制计数器(如 “十进制计数器模块”,实现 0~9 循环)来级联构建。
- 信号解读:
clk
:时钟信号(上升沿触发计数)。reset
:同步复位信号(高电平时,计数器复位到 0)。q[3:0]
:个位的 BCD 值(如波形中依次为 7→8→9→0→1…,实现 0~9 循环)。ena[1]
:十位的使能信号(仅当个位计满 9 时,ena[1]
置高,触发十位递增)。q[7:4]
:十位的 BCD 值(如波形中 5→6→0…,受ena[1]
控制,计满 9 后回 0)。
Solution
module top_module (
input clk,
input reset, // Synchronous active-high reset
output [3:1] ena,
output [15:0] q
);
//实例化四个1位十进制计数器,分别表示个位、十位、百位、千位
count1bit u1 (clk,reset,enas,q[3:0]);
count1bit u2 (clk,reset,ena[1],q[7:4]);
count1bit u3 (clk,reset,ena[2],q[11:8]);
count1bit u4 (clk,reset,ena[3],q[15:12]);
//其中:
wire enas;
assign enas = 1'b1; //个位始终使能
// 生成十位的使能信号:当个位达到9时,ena[1]置高,触发十位计数
assign ena[1] = (q[3:0] == 4'b1001) ? 1'b1 : 1'b0;
// 生成百位的使能信号:当十位和个位都达到9时,ena[2]置高,触发百位计数
assign ena[2] = ((q[7:4] == 4'b1001) && (q[3:0] == 4'b1001)) ? 1'b1 : 1'b0;
assign ena[3] = ((q[11:8] == 4'b1001) && (q[7:4] == 4'b1001) && (q[3:0] == 4'b1001)) ? 1'b1 : 1'b0;
endmodule
//自主构建 1位十进制计数器
module count1bit (
input clk,
input reset,
input ena, // 使能信号:若高电平,则允许该计数器计数
output [3:0] q //4为BCD输出
);
always @(posedge clk) begin
if(reset)
q <= 4'b0000;
else if(ena) begin
if(q == 4'b1001)
q <= 4'b0000;
else
q <= q + 1;
end
else
q <= q; //使能无效时,保持当前值
end
endmodule
12-hour clock
Solution
module top_module(
input clk,
input reset,
input ena,
output pm,
output [7:0] hh,
output [7:0] mm,
output [7:0] ss);
//------------------- 秒计数器(00-59) ---------------------
always @(posedge clk) begin
if (reset)
ss <= 8'd0;
else if (ena) begin
if (ss[3:0] == 4'd9) begin //低位到9
ss[3:0] <= 4'd0; //清零低位
if (ss[7:4] == 4'd5) //低位到9并且高位到5
ss[7:4] <= 4'd0; //清零高位
else
ss[7:4] <= ss[7:4] + 4'd1;
end
else
ss[3:0] <= ss[3:0] + 4'd1;
end
end
//------------------- 分计数器(00-59) ---------------------
always @(posedge clk) begin
if (reset)
mm <= 8'd0;
else if (ena && ss[7:4] == 4'd5 && ss[3:0] == 4'd9) begin //ena有效并且秒数为59时触发使能
if (mm[3:0] == 4'd9)begin //低位到9
mm[3:0] <= 4'd0; //清零低位
if (mm[7:4] == 4'd5) //低位到9并且高位到5
mm[7:4] <= 4'd0; //清零高位
else
mm[7:4] <= mm[7:4] + 4'd1;
end
else
mm[3:0] <= mm[3:0] + 4'd1;
end
end
//------------------- 时计数器(01-12) ---------------------
always @(posedge clk) begin
if (reset) begin
hh[7:4] <= 4'd1; //若直接写hh <= 8'd12; 是错误的,因为这是BCD码。
hh[3:0] <= 4'd2;
pm <= 1'd0;
end
else if (ena &&
mm[7:4] == 4'd5 && mm[3:0] == 4'd9 &&
ss[7:4] == 4'd5 && ss[3:0] == 4'd9) begin //ena有效,并且秒数和分钟都为59时,触发使能
//低位到9并且高位为0 (09:59:59->10:00:00)
if (hh[3:0] == 4'd9 && hh[7:4] == 4'd0) begin
hh[3:0] <= 4'd0;
hh[7:4] <= 4'd1;
end
//低位到2并且高位到1 (12:59:59->01:00:00) ,回绕回01
else if (hh[3:0] == 4'd2 && hh[7:4] == 4'd1) begin
hh[7:4] <= 4'd0;
hh[3:0] <= 4'd1;
end
//低位到1并且高位到1 (11:59:59->12:00:00) ,pm需要转换
else if (hh[3:0] == 4'd1 && hh[7:4] == 4'd1) begin
hh[7:4] <= 4'd1;
hh[3:0] <= 4'd2;
pm <= ~pm;
end
else
hh[3:0] <= hh[3:0] + 4'd1;
end
end
endmodule
一些小问题:
「在 Verilog 中,在always
块中赋值的信号必须声明为reg
型。你的代码中,pm
、hh
、mm
、ss
均在always
块中被赋值,但声明时使用了默认的wire
型(output pm
、output [7:0] hh
等),这会导致编译错误(“非法在 always 块中赋值 wire 型信号”)。」但是,在本问题中,直接赋值依然可以Success,这是因为本网站对语法检查不够严格.