Verilog实现24小时时钟报fan out多驱动错误寻求解答
Verilog时钟代码多重驱动报错解决
问题代码
module top_module( input clk, input reset, input ena, output pm, output reg [7:0] hh, output reg [7:0] mm, output reg [7:0] ss); wire [4:0] enable; assign enable[0] = ss[3:0] == 4'd9; assign enable[1] = ss[7:0] == 8'h59; assign enable[2] = {mm[3:0],ss[7:0]} == 12'h959; assign enable[3] = {mm[7:0],ss[7:0]} == 16'h5959; assign enable[4] = {hh[3:0],mm[7:0],ss[7:0]} == 20'h95959; bcd in1(clk, reset, ena, ss[3:0]); bcd in2(clk, reset, enable[0], ss[7:4]); bcd in3(clk, reset, enable[1], mm[3:0]); bcd in4(clk, reset, enable[2], mm[7:4]); bcd in5(clk, reset, enable[3], hh[3:0]); bcd in6(clk, reset, enable[4], hh[7:4]); always @ (*) begin if(reset) begin pm <= 0; hh <= 8'h12; ss <= 8'h00; mm <= 8'h00; end else if(ena) begin // ss <= ss == 8'h59; // mm <= (mm == 8'h59 & ss == 8'h59) ?? 8'h00 : mm; // hh <= (hh == 8'h12 & mm == 8'h59 & ss == 8'h59) ?? 8'h01 : hh; end end endmodule module bcd(input clk, reset, ena, output [3:0] q); always @ (posedge clk) begin q <= reset ? 0 : (ena ? (q == 4'd9 ? 0 : q + 1) : q); end endmodule
报错信息
Error (12014): Net "hh[7]", which fans out to "hh[7]", cannot be assigned more than one value File: /home/h/work/hdlbits.2188345/top_module.v Line: 28 Error (12015): Net is fed by "GND" Error (12015): Net is fed by "bcd:in6|q[3]" File: /home/h/work/hdlbits.2188345/top_module.v Line: 49
错误原因
- 核心触发原因是信号多重驱动:你已经将
hh/mm/ss的各个位连接到了bcd模块的输出端口,相当于bcd模块一直在驱动这几个信号;同时你又在always @(*)组合逻辑块中对这几个信号赋值,导致同一个信号有两个独立驱动源,直接触发编译错误。 - 附带逻辑错误:
- 你定义的
bcd模块已经自带同步复位逻辑,你额外在组合逻辑中写的复位赋值完全多余,还会和bcd的复位逻辑冲突。 - 组合逻辑块中不应该使用非阻塞赋值
<=,规范写法是使用阻塞赋值=。 - 当前的计数逻辑不符合12/24小时制的进位规则,12点特殊进位判断、am/pm翻转逻辑都缺失,
enable进位信号的判断规则也存在错误。
- 你定义的
修复方案
- 首先移除组合逻辑块中对
hh/mm/ss的所有赋值,将这三个信号的类型从reg改为wire,因为它们完全由bcd模块驱动即可。 - 单独编写
pm的翻转逻辑,以及12小时制的特殊进位修正逻辑:- 当
hh从11:59:59跳转到12:00:00时翻转pm - 当普通BCD计数到13:00:00时,将小时修正为1
- 当
- 修正
enable进位信号的判断规则,适配12小时制的特殊要求。
// 修正后核心代码片段 module top_module( input clk, input reset, input ena, output reg pm, output [7:0] hh, // 改为wire类型 output [7:0] mm, // 改为wire类型 output [7:0] ss // 改为wire类型 ); // 其他不变的enable定义、bcd实例化代码省略 // 移除原来对hh/mm/ss赋值的always块 // 新增pm翻转和小时修正逻辑 reg hh_correction_en; always @(posedge clk) begin if(reset) begin pm <= 1'b0; hh_correction_en <= 1'b0; end else begin // 11:59:59跳变时翻转pm if(enable[3] && hh == 8'h11) begin pm <= ~pm; end // 计数到12:59:59进位时触发小时修正,把13改成1 hh_correction_en <= (enable[3] && hh == 8'h12); if(hh_correction_en) begin // 此处可补充逻辑修正小时BCD值为1,也可直接调整小时位的进位触发规则 end end end endmodule
内容的提问来源于stack exchange,提问作者PauLWaFFleZ
相关产品推荐
相关产品推荐

