verilogdelaysystem-verilogmodelsimtest-bench

Weird Behavior of buffers in modelsim simulation


I ran into a problem that buffer in my simulation does not work as I expected. I tried some test and got the following results. I created code in Verilog that generates two buffers in different ways:

module buffer(
    input wire clk,
    input wire ena,
    output wire buffer,
    output wire buffer2
);
reg buffer_reg = 1'b0;
reg buffer_next = 1'b0;
reg buffer2_reg = 1'b0;

assign buffer = buffer_reg;
assign buffer2 = buffer2_reg;

always @(*) begin
    buffer_next = ena;
end

always @(posedge clk) begin
    buffer_reg <= buffer_next;
    buffer2_reg <= ena;
end
endmodule

Then I simulate it in Modelsim with the following testbench:

`timescale 1ns / 1ns
module buffer_tb();

localparam CLK_CYCLE = 8;

reg clk;
reg ena;
wire buffer;
wire buffer2;

buffer dut(
    .clk(clk),
    .ena(ena),
    .buffer(buffer),
    .buffer2(buffer2)
);

// Clock generation
initial begin
    clk = 1'b0;
end

always #(CLK_CYCLE/2) clk = ~clk;

// Test sequence
initial begin
    // Initialize signals
    ena = 0;

    // change ena values based on the posedge clk
    @(posedge clk) ena = 1;
    @(posedge clk) ena = 0;
        
    repeat(5) @(posedge clk);
        
    @(posedge clk) ena = 1;
    @(posedge clk) ena = 0;
    
    
    repeat(2) #CLK_CYCLE;
    
    // change ena values based on the CLK_CYCLE
    #(CLK_CYCLE) ena = 1;
    #CLK_CYCLE ena = 0;
  
    repeat(5) #CLK_CYCLE;
  
    #CLK_CYCLE ena = 1;
    #CLK_CYCLE ena = 0;

    // Allow simulation to run for a while
    #50 $stop;   // Stop simulation
end
endmodule 

and I get the following result in the simulation:

simulation of buffers in modelsim

Can someone explain why I get different results for buffer2 when I use posedge clk and when I use CLK_CYCLE?


Solution

  • The problem is due to a Verilog simulation race condition in the testbench code.

    If you want to model synchronous behavior, you need to drive the design input signals in the same way that you drive the buffer signals in the design, namely:

    Change the testbench code:

    initial begin
        // Initialize signals
        ena = 0;
    
        // change ena values based on the posedge clk
        @(posedge clk) ena <= 1;
        @(posedge clk) ena <= 0;
            
        repeat(5) @(posedge clk);
            
        @(posedge clk) ena <= 1;
        @(posedge clk) ena <= 0;
    
        repeat(5) @(posedge clk);
            
        @(posedge clk) ena <= 1;
        @(posedge clk) ena <= 0;