У меня есть модуль кода ниже
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, не обновляется не на возрастающем фронте синхроимпульса, а не на следующем возрастающем фронте синхроимпульса..., почему это?? Как я решаю так, чтобы вывод был обновлен на том же положительном возрастающем фронте синхроимпульса?
Вот то, что я имею в виду: сопроводительный текст http://img693.imageshack.us/img693/8660/timing.jpg
ForwardA обновляется с 2 на следующем возрастающем фронте синхроимпульса а не на том же возрастающем фронте синхроимпульса
Я ожидал этой операции. Все дело в том, как управляются ваши входные сигналы, MEMWBRegWrite
и т. Д. Вы должны помнить, что если вы запускаете что-то из часов, то другие синхронизированные блоки не будут видеть это до следующего фронта тактового сигнала, даже если все может выглядеть совпадающим в вашем средстве просмотра сигналов.
Полезно думать о том, что происходит на самом деле. Как только вы запускаете что-то с фронта часов, это не может произойти сразу, будет небольшая задержка. Вы не увидите этих небольших задержек в сигналах RTL sim, но они есть в форме дельта-циклов.
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
установлен на «B» на фронте 2, но для его распространения требуется время. Любые блоки @ (posedge clk)
будут видеть значение «A» для q
на фронте 2 тактового сигнала, оно не будет видеть «B» до следующего фронта, 3. Что это то, что, похоже, вы видите.
Вы можете сгенерировать сигнал почти сразу, если вам это нужно. Но для этого вам понадобится комбинаторная логика ( n1
выше).
wire n1;
assign n1 = q + 1;
или
reg n1;
always @(*)
n1 = q + 1;
Использование последовательной логики (как вы):
reg n2;
always @(posedge clk)
n2 <= q + 1;
Обратите внимание на '<='. Это неблокирующее назначение - рекомендуется использовать его для назначения вещей, которые вы хотите использовать в качестве регистров или флопов в своем дизайне. Взгляните на статьи о дизайне Sunburst для лучшего объяснения.