#system-verilog #test-bench #flip-flop
#system-verilog #тестовый стенд #триггер
Вопрос:
Мне нужно реализовать тестовый стенд для модуля 4 flipflops, который находится в design.sv интерфейс. Модули foo1, foo2 и bar2 работают правильно (вы можете видеть это при запуске, ожидаемые значения совпадают с выходными значениями), за исключением bar1. Я не знаю, почему это происходит. https://www.edaplayground.com/x/XaWu
//testbench for the bar1 flip flop.
module general_tb3 (
);
logic a, b, c, clk;
logic x, y, w;
bar1 uut(a, b, c, clk, x, y, w);
initial
begin
$dumpfile("dump.vcd");
$dumpvars(1);
end
function logic output_x3;
input a, b;
begin
output_x3 <= a | b;
end
endfunction
function logic output_y3;
input a, b, c;
begin
output_y3 <= ~((a | b) amp; c);
end
endfunction
function logic output_w3;
input a, b, c;
begin
output_w3 <= a | ~((a | b) amp; c);
end
endfunction
// Seção de testes com atribuição de valores para f e f_expected
initial
begin
#10000 $display("nBar1 tests");
#10000 $display ("| a | b | c | clk | x | y | w | x_expected | y_expected| w_expected|");
a = 0; b = 0; c = 0; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 0), output_y3(0, 0, 0), output_w3(0, 0, 0) );
a = 0; b = 0; c = 0; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 0), output_y3(0, 0, 0), output_w3(0, 0, 0) );
a = 0; b = 0; c = 1; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 0), output_y3(0, 0, 1), output_w3(0, 0, 1) );
a = 0; b = 0; c = 1; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 0), output_y3(0, 0, 1), output_w3(0, 0, 1) );
a = 0; b = 1; c = 0; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 0), output_y3(0, 1, 0), output_w3(0, 1, 0) );
a = 0; b = 1; c = 0; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 1), output_y3(0, 1, 0), output_w3(0, 1, 0) );
a = 0; b = 1; c = 1; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 1), output_y3(0, 1, 1), output_w3(0, 1, 1) );
a = 0; b = 1; c = 1; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(0, 1), output_y3(0, 1, 1), output_w3(0, 1, 1) );
a = 1; b = 0; c = 0; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 0), output_y3(1, 0, 0), output_w3(1, 0, 0) );
a = 1; b = 0; c = 0; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 0), output_y3(1, 0, 0), output_w3(1, 0, 0) );
a = 1; b = 0; c = 1; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 0), output_y3(1, 0, 1), output_w3(1, 0, 1) );
a = 1; b = 0; c = 1; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 0), output_y3(1, 0, 1), output_w3(1, 0, 1) );
a = 1; b = 1; c = 0; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 1), output_y3(1, 1, 0), output_w3(1, 1, 0) );
a = 1; b = 1; c = 0; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 1), output_y3(1, 1, 0), output_w3(1, 1, 0) );
a = 1; b = 1; c = 1; clk = 0;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 1), output_y3(1, 1, 1), output_w3(1, 1, 1) );
a = 1; b = 1; c = 1; clk = 1;
#10000 $display("| %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h | %0h |", a, b, c, clk, x, y, w, output_x3(1, 1), output_y3(1, 1, 1), output_w3(1, 1, 1) );
end
endmodule
Дизайн для этого триггера:
module bar1 (a, b, c, clk, x, y, w);
input a, b, c, clk;
output reg x, y, w;
always @(negedge clk)
begin
x <= a | b;
y <= ~(x amp; c);
w <= a | y;
end
endmodule
ВЫВОДИТ:
# KERNEL: Bar1 tests
# KERNEL: | a | b | c | clk | x | y | w | x_expected | y_expected| w_expected|
# KERNEL: | 0 | 0 | 0 | 0 | 0 | 1 | x | x | x | x |
# KERNEL: | 0 | 0 | 0 | 1 | 0 | 1 | x | 0 | 1 | 1 |
# KERNEL: | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
# KERNEL: | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
# KERNEL: | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 |
# KERNEL: | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
# KERNEL: | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
# KERNEL: | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 |
# KERNEL: | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 |
# KERNEL: | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
# KERNEL: | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
# KERNEL: | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
# KERNEL: | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 1 |
# KERNEL: | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
# KERNEL: | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
# KERNEL: | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
Ответ №1:
Рассмотрим этот дизайн тестового стенда.
Создайте синхронизацию отдельно от других входных сигналов. Затем запустите все на краю часов.
Используйте for
цикл для управления другими входными данными.
Смоделируйте свой дизайн, используя x_exp
сигнал. Это генерируется с тем же временем, x
что и сигнал проектирования.
Используйте противоположный край часов для отображения всех значений; это позволяет избежать условий гонки.
module general_tb3;
bit a, b, c, clk;
logic x, y, w;
logic x_exp;
bar1 uut(a, b, c, clk, x, y, w);
initial begin
$dumpfile("dump.vcd");
$dumpvars(1);
end
always #10_000 clk = ~clk;
initial begin
for (int i=0; i<8; i ) begin
@(negedge clk) {a, b, c} <= i;
end
@(negedge clk);
#5 $finish;
end
always @(negedge clk) x_exp <= (a | b);
initial begin
@(posedge clk); // Avoid unknowns at the start
forever @(posedge clk) begin
$display($time, " abc=b x=%b x_exp=%b", {a, b, c}, x, x_exp);
end
end
endmodule
Вы можете добавить ожидаемые значения для y
и w
.
Вот результат:
30000 abc=000 x=0 x_exp=0
50000 abc=001 x=0 x_exp=0
70000 abc=010 x=0 x_exp=0
90000 abc=011 x=1 x_exp=1
110000 abc=100 x=1 x_exp=1
130000 abc=101 x=1 x_exp=1
150000 abc=110 x=1 x_exp=1
170000 abc=111 x=1 x_exp=1
Чтобы избавиться от неизвестных значений в начале моделирования, вы можете использовать сигнал сброса для вашего проекта.
Комментарии:
1. Большое вам спасибо @toolic . Теперь каждый получает то, что от него ожидали.
2. @Connor если это ответило на ваш вопрос, пожалуйста, отметьте его как принятый.
Ответ №2:
Ваши function
s используют неблокирующие назначения ( <=
). они должны использовать блокирующие назначения ( =
).
При неблокирующих назначениях выполняется немедленная оценка, но обновления после выполнения всех других операций могут быть выполнены. Поэтому в то $display
время как выводится устаревшее значение.
В общем, неблокирующее должно использоваться для синхронной логики (например always @(posedge clock)
, и всего, что обновляется по фронтам синхронизации), в то время как блокировка должна использоваться для комбинационной логики (по большей части все остальное).