Испытательный стенд флип-флоп показывает неверные значения

Мне нужно реализовать тестовую среду для модуля с 4 триггерами, которые находятся в интерфейсе 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) & c);
      end
  endfunction
  
  function logic output_w3;
    input a, b, c;
      begin
        output_w3 <= a | ~((a | b) & 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 & 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         |

person Connor    schedule 17.11.2020    source источник


Ответы (2)


Рассмотрим этот дизайн тестового стенда.

Создайте часы отдельно от других входных сигналов. Затем водите все по краю часов.

Используйте петлю 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=%03b 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

Чтобы избавиться от неизвестных значений в начале моделирования, вы можете использовать сигнал сброса для своего дизайн.

person toolic    schedule 18.11.2020
comment
Большое спасибо @toolic. Теперь все получают то, что от них ожидали. - person Connor; 18.11.2020
comment
@Connor, если это ответ на ваш вопрос, отметьте его как принятый. - person Aaron; 25.11.2020

Ваши functions используют неблокирующие назначения (<=). они должны использовать блокирующие назначения (=).

При неблокирующем назначении оценивается немедленно, но обновляется после того, как все остальные операции имеют возможность выполнить. Следовательно, $display при выводе устаревшего значения.

В общем, неблокирование следует использовать для синхронной логики (например, always @(posedge clock) и вещи, которые обновляются по фронтам тактовых импульсов), в то время как блокирование следует использовать для комбинационной логики (по большей части для всего остального).

person Greg    schedule 18.11.2020