Connor
Connor

Reputation: 43

Flip flop testbench shows incorrect values

I need to implement the testbench for the 4 flipflops module that are in the design.sv interface. The modules foo1, foo2 and bar2 are working properly (you can see this when you run, the expected values are the same as the output values) except the bar1. I don't know why this is happening. 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

Design for this flip flop:

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

OUTPUTS:


# 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         |

Upvotes: 2

Views: 365

Answers (2)

toolic
toolic

Reputation: 62236

Consider this testbench design.

Create the clock separate from the other input signals. Then, drive everything on the edge of a clock.

Use a for loop to drive your other inputs.

Model your design using the x_exp signal. This is generated with the same timing as the design x signal.

Use the opposite edge of the clock to display all the values; this avoids race conditions.

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

You can add expected values for y and w.

Here is the output:

           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

To get rid of unknown values at the start of simulation, you could use a reset signal for your design.

Upvotes: 1

Greg
Greg

Reputation: 19122

Your functions are using non-blocking assignments (<=). they should be using blocking assignments (=).

With non-blocking assignments evaluates immediately but updates after all other operations have an opportunity to execute. Therefore a the $display while output a stale value.

In general, non-blocking should be used for synchronous logic (ex always @(posedge clock) and things that update on clock edges) while blocking should be used for combinational logic (for the most part everything else).

Upvotes: 0

Related Questions