// ❌ 错误示例:判断条件不对,导致计数到9后没有正确回0 always @(posedge clk) begin if (reset) begin q <= 4'd0; end elseif (q == 4'd10) begin// 应该是q == 4'd9! q <= 4'd0; end elsebegin q <= q + 1'd1; end end
// ✅ 正确示例:在q == 9时就判断要回0 always @(posedge clk) begin if (reset) begin q <= 4'd0; end elseif (q == 4'd9) begin// 计数到9,下一个是0 q <= 4'd0; end elsebegin q <= q + 1'd1; end end
// ❌ 错误示例:在组合逻辑always块中写计数器 always @(*) begin if (reset) begin q = 4'd0; end elsebegin q = q + 1'd1; // 这里会形成组合环路! end end
错误原因分析:
计数器必须用时序逻辑(时钟边沿触发)来实现!如果用组合逻辑来写,会形成无限循环,电路会不停地振荡。
正确做法对比:
1 2 3 4 5 6 7 8 9
// ✅ 正确示例:用时序逻辑always块 always @(posedge clk) begin if (reset) begin q <= 4'd0; end elsebegin q <= q + 1'd1; end end
错误4:使能信号处理不当
错误表现:
1 2 3 4 5 6 7 8 9 10
// ❌ 错误示例:没有使能信号时,计数器在else分支没有保持原值 always @(posedge clk) begin if (reset) begin q <= 4'd0; end elseif (enable) begin q <= q + 1'd1; end // 缺少else分支!虽然综合器会自动保持,但显式写出来更清晰 end
// ✅ 正确示例:显式写出所有情况 always @(posedge clk) begin if (reset) begin q <= 4'd0; end elseif (enable) begin if (q == 4'd9) begin q <= 4'd0; end elsebegin q <= q + 1'd1; end end elsebegin q <= q; // 显式保持 end end
always @(posedge clk) begin if (reset) begin q <= 4'd0; end elseif (slowena) begin if (q == 4'd9) begin q <= 4'd0; // 计数到9,回到0 end elsebegin q <= q + 4'd1; end end // else分支:slowena=0时,保持q不变 end
// 个位计数器 always @(posedge clk) begin if (reset) begin ones <= 4'd0; end elseif (ones == 4'd9) begin ones <= 4'd0; end elsebegin ones <= ones + 4'd1; end end
// 十位计数器 always @(posedge clk) begin if (reset) begin tens <= 4'd0; end elseif (tens == 4'd9 && ones == 4'd9) begin tens <= 4'd0; end elseif (ones == 4'd9) begin tens <= tens + 4'd1; end end
// 百位计数器 always @(posedge clk) begin if (reset) begin hundreds <= 4'd0; end elseif (hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) begin hundreds <= 4'd0; end elseif (tens == 4'd9 && ones == 4'd9) begin hundreds <= hundreds + 4'd1; end end
// 千位计数器 always @(posedge clk) begin if (reset) begin thousands <= 4'd0; end elseif (thousands == 4'd9 && hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) begin thousands <= 4'd0; end elseif (hundreds == 4'd9 && tens == 4'd9 && ones == 4'd9) begin thousands <= thousands + 4'd1; end end
always @(posedge clk) begin if (reset) begin ss_ones <= 4'd0; end elseif (add_ss_ones) begin if (end_ss_ones) begin ss_ones <= 4'd0; end elsebegin ss_ones <= ss_ones + 4'd1; end end end
always @(posedge clk) begin if (reset) begin ss_tens <= 4'd0; end elseif (add_ss_tens) begin if (end_ss_tens) begin ss_tens <= 4'd0; end elsebegin ss_tens <= ss_tens + 4'd1; end end end
always @(posedge clk) begin if (reset) begin mm_ones <= 4'd0; end elseif (add_mm_ones) begin if (end_mm_ones) begin mm_ones <= 4'd0; end elsebegin mm_ones <= mm_ones + 4'd1; end end end
always @(posedge clk) begin if (reset) begin mm_tens <= 4'd0; end elseif (add_mm_tens) begin if (end_mm_tens) begin mm_tens <= 4'd0; end elsebegin mm_tens <= mm_tens + 4'd1; end end end
always @(posedge clk) begin if (reset) begin hh_ones <= 4'd2; // 复位到12点,个位是2 end elseif (add_hh_ones) begin if (end_hh_ones_0) begin hh_ones <= 4'd0; end elseif (end_hh_ones_1) begin hh_ones <= 4'd1; // 12点后回到1点 end elsebegin hh_ones <= hh_ones + 4'd1; end end end
always @(posedge clk) begin if (reset) begin hh_tens <= 4'd1; // 复位到12点,十位是1 end elseif (add_hh_tens) begin if (end_hh_tens_0) begin hh_tens <= 4'd0; // 12点后变成0 end elseif (end_hh_tens_1) begin hh_tens <= hh_tens + 4'd1; end end end
// ====================== AM/PM标志 ====================== always @(posedge clk) begin if (reset) begin pm_temp <= 1'd0; // 复位到中午,AM end elseif (pm_ding) begin pm_temp <= ~pm_temp; // 11:59:59 AM → 12:00:00 PM end end