能否在 verilog 中的 always 块内合成时钟边沿事件?
Can clock edge events be synthesized inside always blocks in verilog?
我有两个时钟,clk0 和 clk1。我想要一个计数器来计数 clk0 的 posedge 但在 clk1 的 posedge 重置。需要注意的重要一点是,复位应该只发生在 posedge 上,而不是在 clk1 为高电平时。所以下面的代码是不可能的。
always @(posedge clk0 or posedge clk1)
begin
if (clk1)
count <= 0;
else
count <= count + 1;
end
我们也不能从两个 always 块中驱动计数器。所以下面是不可能的:
always @ (posedge clk0)
begin
count <= count + 1;
end
always @ (posedge clk1)
begin
count <= 0;
end
所以我的问题是:什么提供了类似
的功能
always @(posedge clk0 or posedge clk1)
begin
if (posedge clk1)
count <= 0;
else
count <= count + 1;
end
可合成吗?
我想要一个计数器,它在 clk0 的 posedge 上计数并在 clk1 的 posedge 上重置。 clk0 比 clk1 快一个数量级。设计需要可综合。
您需要将 'event' 从 clk1 转移到 clk0。这是一个时钟域交叉问题,因此需要同步。
reg clk1_meta,clk1_sync,clk1_prev;
always @(posedge clk0 or negedge reset_n) // async low reset as example
begin
if (!reset_n)
begin
clk1_meta <= 1'b0;
clk1_sync <= 1'b0;
clk1_prev <= 1'b0;
counter <= 'b0;
end
else
begin
// transfer clk1 to clk0
clk1_meta <= clk1;
clk1_sync <= clk1_meta;
// Now we have a safe signal: clk1_sync
clk1_prev <= clk1_sync;
// A rising edge is when clk1_sync1 is high but previously it was low
if (clk1_sync==1'b1 && clk1_prev==1'b0)
counter <= 'b0;
else
counter <= counter + 1;
end
end
由于同步,在 clk1 到达 clk0 域之前不可避免地延迟了约 2 个 clk0 时钟周期。
我有两个时钟,clk0 和 clk1。我想要一个计数器来计数 clk0 的 posedge 但在 clk1 的 posedge 重置。需要注意的重要一点是,复位应该只发生在 posedge 上,而不是在 clk1 为高电平时。所以下面的代码是不可能的。
always @(posedge clk0 or posedge clk1)
begin
if (clk1)
count <= 0;
else
count <= count + 1;
end
我们也不能从两个 always 块中驱动计数器。所以下面是不可能的:
always @ (posedge clk0)
begin
count <= count + 1;
end
always @ (posedge clk1)
begin
count <= 0;
end
所以我的问题是:什么提供了类似
的功能always @(posedge clk0 or posedge clk1)
begin
if (posedge clk1)
count <= 0;
else
count <= count + 1;
end
可合成吗?
我想要一个计数器,它在 clk0 的 posedge 上计数并在 clk1 的 posedge 上重置。 clk0 比 clk1 快一个数量级。设计需要可综合。
您需要将 'event' 从 clk1 转移到 clk0。这是一个时钟域交叉问题,因此需要同步。
reg clk1_meta,clk1_sync,clk1_prev;
always @(posedge clk0 or negedge reset_n) // async low reset as example
begin
if (!reset_n)
begin
clk1_meta <= 1'b0;
clk1_sync <= 1'b0;
clk1_prev <= 1'b0;
counter <= 'b0;
end
else
begin
// transfer clk1 to clk0
clk1_meta <= clk1;
clk1_sync <= clk1_meta;
// Now we have a safe signal: clk1_sync
clk1_prev <= clk1_sync;
// A rising edge is when clk1_sync1 is high but previously it was low
if (clk1_sync==1'b1 && clk1_prev==1'b0)
counter <= 'b0;
else
counter <= counter + 1;
end
end
由于同步,在 clk1 到达 clk0 域之前不可避免地延迟了约 2 个 clk0 时钟周期。