如何修改Verilog代码避免多驱动?
How to modify the Verilog code to avoid multiple drivers?
Quartus 11.0 说:
Error (10028): Can't resolve multiple constant drivers for net "n[9]"
对于以下代码:
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
always @(posedge h)
begin
n<=0;
end
always @(negedge clk)
begin
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
assign P=r;
endmodule
########### image is here ###########
我要的就是这张图。 flag1开始时设置n=0,并计数clk;
当计数到flag2时,设置P=0;数到红色箭头时,设P=1;
正如警告所说,n[9]
有多个驱动程序,实际上 n
和 r
都有,因为 n
和 r
是在 initial
和 always
中都被驱动,并且在综合设计时,一个 reg 只能有一个驱动程序。并且 n
在多个 always
块中驱动。
对于综合,一个 reg 应该只从一个 always
块中驱动。
对于驱动n
的多个always块,将它们合并为一个,并且只使用一个时钟,例如clk
.
如果目的是为 n
和 r
分配默认值,则在声明中进行,并删除 initial
,如:
reg r = 1'b1;
reg[9:0] n = 0;
但是,如果可能,请考虑添加一个复位信号,然后使用此复位信号将复位值同步或异步地分配给寄存器。
假设 h
与 clk
同步,只需对 h
进行采样并找出何时采样值较低而当前值较高(例如 h
rose ).这样 n
在一个 always 块中分配(这是综合所必需的)并且所有内容都是相同的时钟域。
always @(negedge clk) begin
past_h <= h;
if(!past_h && h) begin // detect 0->1
n <= 10'h000;
end
else begin
n <= n + 1'b1;
end
end
如果 h
是异步的,那么保持信号干净的事情就会变得更加复杂。在这种情况下,我建议阅读 Cliff Cummings
的 Clock Domain Crossing (CDC) Design & Verification Techniques
我想它会对你有所帮助。我已经在xilinx 14.5 synthesis done中编译了这个。
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
task cpu_write;
begin
@ (posedge h);
n <= 0;
@ (posedge clk);
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
endtask
assign P=r;
endmodule
您可以尝试将posedge h 移动到与negedge clock 相同的always 块中,并根据输入逻辑对h 和clk 进行采样。如果 h 在 clk 的否定之前变低,那么这样的事情可能会起作用。
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
always @(negedge clk, posedge h)
begin
if(h==1'b1)
n<=0;
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
assign P=r;
endmodule
Quartus 11.0 说:
Error (10028): Can't resolve multiple constant drivers for net "n[9]"
对于以下代码:
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
always @(posedge h)
begin
n<=0;
end
always @(negedge clk)
begin
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
assign P=r;
endmodule
########### image is here ###########
我要的就是这张图。 flag1开始时设置n=0,并计数clk; 当计数到flag2时,设置P=0;数到红色箭头时,设P=1;
正如警告所说,n[9]
有多个驱动程序,实际上 n
和 r
都有,因为 n
和 r
是在 initial
和 always
中都被驱动,并且在综合设计时,一个 reg 只能有一个驱动程序。并且 n
在多个 always
块中驱动。
对于综合,一个 reg 应该只从一个 always
块中驱动。
对于驱动n
的多个always块,将它们合并为一个,并且只使用一个时钟,例如clk
.
如果目的是为 n
和 r
分配默认值,则在声明中进行,并删除 initial
,如:
reg r = 1'b1;
reg[9:0] n = 0;
但是,如果可能,请考虑添加一个复位信号,然后使用此复位信号将复位值同步或异步地分配给寄存器。
假设 h
与 clk
同步,只需对 h
进行采样并找出何时采样值较低而当前值较高(例如 h
rose ).这样 n
在一个 always 块中分配(这是综合所必需的)并且所有内容都是相同的时钟域。
always @(negedge clk) begin
past_h <= h;
if(!past_h && h) begin // detect 0->1
n <= 10'h000;
end
else begin
n <= n + 1'b1;
end
end
如果 h
是异步的,那么保持信号干净的事情就会变得更加复杂。在这种情况下,我建议阅读 Cliff Cummings
我想它会对你有所帮助。我已经在xilinx 14.5 synthesis done中编译了这个。
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
task cpu_write;
begin
@ (posedge h);
n <= 0;
@ (posedge clk);
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
endtask
assign P=r;
endmodule
您可以尝试将posedge h 移动到与negedge clock 相同的always 块中,并根据输入逻辑对h 和clk 进行采样。如果 h 在 clk 的否定之前变低,那么这样的事情可能会起作用。
module make_counter(h, clk, P);
input wire h;
input wire clk;
output wire P;
reg r=1'b1;
reg[9:0] n=10'b0000000000;
always @(negedge clk, posedge h)
begin
if(h==1'b1)
n<=0;
if(n<600)
n<=n+1'b1;
if(n==106)
r<=1'b0;
else if(n==517)
r<=1'b1;
else;
end
assign P=r;
endmodule