Тестовый стенд с триггером показывает неправильные значения

#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) , и всего, что обновляется по фронтам синхронизации), в то время как блокировка должна использоваться для комбинационной логики (по большей части все остальное).