我在eda操场上做了一个基本示例,说明了所遇到的问题。 假设我有两个时钟1x和2x。使用触发器分频器将2x从1x进行除。
我有两个寄存器a和b。 a以1x计时,b以2x计时。
b是a的采样值。
当我们有1x和2x时钟的上升沿时,b不是采用a的期望值,而是采用下一个周期值。
这是因为采用了这种时钟分频器方案,因此,如果我们使用icgs进行分频并且可以正常工作。 但是,是否有一种方法可以将这种时钟分频器方案与触发器一起使用?
EDA游乐场链接:https://www.edaplayground.com/x/map#
module race_test;
logic clk1x = 0;
logic clk2x = 0;
always
#5ns clk1x = !clk1x;
int a, b;
always @(posedge clk1x) begin
a <= a+1;
clk2x <= !clk2x;
end
// Problem here is that b will sample postpone value of a
// clk2x is not triggering at the same time than clk1x but a bit later
// This can be workaround by putting blocking assignment for clock divider
always @(posedge clk2x) begin
b <= a;
end
initial begin
$dumpfile("test.vcd");
$dumpvars;
#1us
$stop;
end
endmodule
答案 0 :(得分:1)
数字时钟分频器在仿真和物理时序上都存在问题。
Verilog的非阻塞赋值运算符假定每个读取和写入相同变量的人都同步到同一时钟事件。通过使用NBA对clk2x
的书写,您已经将a
的读数移到了另一个 delta 时间*,并且您发现a
已被更新。 。
在实际硬件中,存在很大的传播延迟,通常可以避免这种情况。但是,您使用相同的D触发器来分配给clk2x
,因此那里也会有传播延迟。您上一个always
块现在代表时钟域交叉问题。因此,根据两个时钟之间的时滞,您可能仍会处于竞争状态。
一种解决方法是使用时钟频率更高的时钟发生器模块
always #2.5ns clk = !clk;
always @(posedge clk) begin
clk1x <= !clk1x;
if (clk1x == 1)
clk2x = !clk2x;