我有下面的代码模块
always @(posedge Clk) begin
ForwardA = 0;
ForwardB = 0;
//EX Hazard
if (EXMEMRegWrite == 1) begin
if (EXMEMrd != 0)
if (EXMEMrd == IDEXrs)
ForwardA = 2'b10;
if (EXMEMrd == IDEXrt && IDEXTest == 0)
ForwardB = 2'b10;
end
//MEM Hazard
if (MEMWBRegWrite == 1) begin
if (MEMWBrd != 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
if (MEMWBrd == IDEXrs)
ForwardA = 2'b01;
if (IDEXTest == 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
if (MEMWBrd == IDEXrt)
ForwardB = 2'b01;
end
end
end
end
问题是输出,即ForwardA和ForwardB不是在时钟上升沿而不是在下一个上升时钟边沿上更新...为什么这?如何解决,以便在相同的正上升时钟边沿更新输出?
这就是我的意思: alt text http://img693.imageshack.us/img693/8660/timing.jpg
ForwardA在下一个上升时钟沿更新为2,而不是在同一个上升时钟沿
答案 0 :(得分:2)
我期待这个操作。这与您的输入信号MEMWBRegWrite
等的驱动方式有关。你必须记住,如果你从一个时钟启动一些东西,那么其他时钟块在下一个时钟边缘之前就不会看到它,即使你的波形查看器看起来可能看起来很重合。
想一想正在发生的事情的现实是有帮助的。一旦从时钟边缘启动某些东西,就不会马上发生这种情况,会有一点延迟。你不会在RTL sim波形中看到这些小的延迟,但它们以delta周期的形式存在。
1 2 3
______ ______
clk __| |______| |______|
q ----<======A======X=======B======X====
n1 -----<====A+1======X======B+1=====X===== (combinatorial/logic)
n2 ------------------X======A+1=====X=====B+1 (sequential/clocked)
如果你看一下上面我非常聪明的ascii艺术,q
在时钟边缘2被设置为'B',但这需要时间来传播。任何@(posedge clk)
块在时钟边缘2上看到q
的值为'A',在下一个边缘之前不会看到'B',3。看起来你是什么样的看到。
如果你需要的话,你几乎可以直接发出信号。但要做到这一点,你需要使用组合逻辑(上面n1
)。
wire n1;
assign n1 = q + 1;
或
reg n1;
always @(*)
n1 = q + 1;
使用顺序逻辑(就像你一样):
reg n2;
always @(posedge clk)
n2 <= q + 1;
注意'&lt; ='。这是一个非阻塞任务 - 建议使用它来分配你想要在你的设计中注册或触发的东西。请查看Sunburst Design论文,以获得更好的解释。