#verilog #test-bench
Вопрос:
Я пишу модуль D-триггера, как показано ниже:
module mod1(
input clk,
input d,
output reg q
);
always @(posedge clk)begin
q <= d;
end
endmodule
Это два фрагмента кода, которые я использовал для тестирования своего модуля mod1
// code 1
module mod1_tb;
reg clk;
reg d;
wire q;
mod1 dut(
.clk(clk),
.d(d),
.q(q)
);
always #10 clk = ~clk;
initial begin
clk = 0;
@(posedge clk)
d <= 0;
@(posedge clk)
d <= 1;
@(posedge clk)
d <= 0;
@(posedge clk)
d <= 1;
end
endmodule
Форму волны можно увидеть следующим образом:
// code 2
module mod1_tb;
reg clk;
reg d;
wire q;
mod1 dut(
.clk(clk),
.d(d),
.q(q)
);
always #10 clk = ~clk;
initial begin
clk = 0;
@(posedge clk);
d = 0;
@(posedge clk);
d = 1;
@(posedge clk);
d = 0;
@(posedge clk);
d = 1;
end
endmodule
Форму волны можно увидеть следующим образом:
На мой взгляд, все они должны хорошо работать, но результат показывает, что работает только первый способ. Я немного смущен тем, почему второй вариант не работает.
Ответ №1:
Предполагается, что ваш входной сигнал ( d
) синхронен с часами. Вы должны управлять этим сигналом в своем тестовом стенде аналогично тому, как он управляется в дизайне. Используйте @(posedge clk)
, как вы уже делаете, и используйте неблокирующие назначения ( <=
) вместо блокировки ( =
).
Ваш code 1
компьютер правильно использует неблокирующуюся среду в тестовом стенде, поэтому он имитирует так, как вы ожидаете.
Вы code 2
используете блокировку в тестовой среде, поэтому она не имитируется должным образом.
Неблокирующее назначение гарантирует, что симулятор выполнит выборку синхронного ввода в то время, когда вы этого ожидаете.
Рекомендуемая надлежащая практика кодирования заключается в использовании неблокирующего для последовательной логики, такой как триггеры.
Существует множество литературы, в которой обсуждаются детали планирования событий Verilog. Вот одна статья.