为什么模块的输出无法从外部模块到达
why output of a module can't reach from outside module
我用Verilog写了两个模块。
第一个模块是 4 位计数器:
module ASYNCHRONOUS_COUNTER( clk, res, out);
input clk;
input res;
output[3:0] out;
reg[3:0] out;
wire clk;
wire res;
initial
out = 4'b0;
always @(negedge clk or posedge res)
if(res) begin
out[0] <= 1'b0;
end else begin
out[0] <= ~out[0];
end
always @(negedge out[0] or posedge res)
if(res) begin
out[1] <= 1'b0;
end else begin
out[1] <= ~out[1];
end
always @(negedge out[1] or posedge res)
if(res) begin
out[2] <= 1'b0;
end else begin
out[2] <= ~out[2];
end
always @(negedge out[2] or posedge res)
if(res) begin
out[3] <= 1'b0;
end else begin
out[3] <= ~out[3];
end
endmodule
第二个模块使用第一个模块:
module tripleInputClk(clk,tripledClk);
input clk;
wire clk;
output tripledClk;
wire tripledClk;
wire res;
wire[3:0] out;
reg temp;
initial
temp <= 1'b0;
//assign out = 3'b0;
assign res = ~out[3] & ~out[2] & out[1] & out[0];
ASYNCHRONOUS_COUNTER myCounter(
.clk(clk),
.res(res),
.out(out)
);
always @(posedge res)
begin
temp <= ~temp;
end
assign tripledClk = temp;
endmodule
第一个模块工作正常,但是当我编译它并制作它的波形时,我明白第一个模块的输出没有正确通过并且 'res' 的值总是等于'0'。
此处,res
在您的 tripleInputClk
模块中声明为 wire
。
我模拟了您的代码并观察到信号 tripledClk
在 三个 时钟脉冲后变为高电平。因此,怀疑必须发生 posedge
of res
信号。但是,res
是连续赋值语句。一旦 res
变为 HIGH,reg out
就会改变 (@(posedge res)
) 并再次使 res
LOW ;所有这些 都在一个时间戳 中完成。所以您无法查看 res 信号的转换。
而且,在那之后,tripledClk
信号没有按预期切换,我猜。
一种解决方法是在 tripleInputClk
模块中将 res
声明为 reg
,然后 将其从连续赋值中删除 。相反,使其仅在时钟信号的 edge 上工作。
这是因为,reg是用来存储值的。这里,res
在 out
上存在 循环依赖性 ,反之亦然(即 out
也依赖于 res
) .从今以后,它创造了某种令人困惑的条件(我不会将其准确地称为围绕条件的竞赛)。
当您继续进行综合时(即使 initial 块在此处不可综合......!),该工具可能会发出此循环依赖性 警告。并且,可能无法形成适当的硬件。
我已经修改了您的代码并为其提供了一个 testbench。唯一的变化是我在这里描述的变化,即 res
信号。请仔细阅读下面的link。 tripledClk
现在也可以正常工作 (3*frequency_of_clk)。
Link 到 EDAPlayground.
我用Verilog写了两个模块。 第一个模块是 4 位计数器:
module ASYNCHRONOUS_COUNTER( clk, res, out);
input clk;
input res;
output[3:0] out;
reg[3:0] out;
wire clk;
wire res;
initial
out = 4'b0;
always @(negedge clk or posedge res)
if(res) begin
out[0] <= 1'b0;
end else begin
out[0] <= ~out[0];
end
always @(negedge out[0] or posedge res)
if(res) begin
out[1] <= 1'b0;
end else begin
out[1] <= ~out[1];
end
always @(negedge out[1] or posedge res)
if(res) begin
out[2] <= 1'b0;
end else begin
out[2] <= ~out[2];
end
always @(negedge out[2] or posedge res)
if(res) begin
out[3] <= 1'b0;
end else begin
out[3] <= ~out[3];
end
endmodule
第二个模块使用第一个模块:
module tripleInputClk(clk,tripledClk);
input clk;
wire clk;
output tripledClk;
wire tripledClk;
wire res;
wire[3:0] out;
reg temp;
initial
temp <= 1'b0;
//assign out = 3'b0;
assign res = ~out[3] & ~out[2] & out[1] & out[0];
ASYNCHRONOUS_COUNTER myCounter(
.clk(clk),
.res(res),
.out(out)
);
always @(posedge res)
begin
temp <= ~temp;
end
assign tripledClk = temp;
endmodule
第一个模块工作正常,但是当我编译它并制作它的波形时,我明白第一个模块的输出没有正确通过并且 'res' 的值总是等于'0'。
此处,res
在您的 tripleInputClk
模块中声明为 wire
。
我模拟了您的代码并观察到信号 tripledClk
在 三个 时钟脉冲后变为高电平。因此,怀疑必须发生 posedge
of res
信号。但是,res
是连续赋值语句。一旦 res
变为 HIGH,reg out
就会改变 (@(posedge res)
) 并再次使 res
LOW ;所有这些 都在一个时间戳 中完成。所以您无法查看 res 信号的转换。
而且,在那之后,tripledClk
信号没有按预期切换,我猜。
一种解决方法是在 tripleInputClk
模块中将 res
声明为 reg
,然后 将其从连续赋值中删除 。相反,使其仅在时钟信号的 edge 上工作。
这是因为,reg是用来存储值的。这里,res
在 out
上存在 循环依赖性 ,反之亦然(即 out
也依赖于 res
) .从今以后,它创造了某种令人困惑的条件(我不会将其准确地称为围绕条件的竞赛)。
当您继续进行综合时(即使 initial 块在此处不可综合......!),该工具可能会发出此循环依赖性 警告。并且,可能无法形成适当的硬件。
我已经修改了您的代码并为其提供了一个 testbench。唯一的变化是我在这里描述的变化,即 res
信号。请仔细阅读下面的link。 tripledClk
现在也可以正常工作 (3*frequency_of_clk)。
Link 到 EDAPlayground.