0
votes

I have made a counter module and I can't seem to grasp the execution order of initial block for both counter module and testbench module.

As far as I know, I thought in verilog, initial block would always be executed first.

In this case, I'll be executing testbench module and I am assuming initial block for testbench_counter will be executed first.

Next, I thought counter module C would be executed and value for x_in would be updated to temp with no need for #1 delay in module C.

But without #1, or changing initial to always@(x_in) I see redline.

So the question is

  1. would initial block for counter module C be executed first even before the initial block for testbench?

  2. Why does it work if i use always@(x_in)?

Thanks in advance.

Code for counter

`timescale 1ns/1ns
module counter(x_in,clk,y_out);
    input [31:0] x_in;
    input clk;
    output [31:0] y_out;
    reg [31:0] y_out;
    reg [31:0] temp;

    initial begin
        #1 temp=x_in;
    end

    always@(posedge clk) begin
        temp<=temp+1;   
        y_out<=temp;
    end
endmodule

code for testbench

`timescale 1ns/1ns

module testbench_conter();
    wire [31:0]y_out;
    wire [31:0]temp;
    reg [31:0]x_in;
    reg clk;

    counter C(x_in,clk,y_out);

    always begin
        #5 clk=~clk;
    end

    initial begin
        clk=1'b0; 
        x_in=32'd0;
        #0
        #10000
        $stop;
    end
endmodule
2

2 Answers

2
votes

Next, I thought counter module C would be executed...

The major flaw in your thinking is that the initial statement in the counter is executed when the counter is "executed". This is not the case. All initial statements are run at start of the program, and only once. Thus your two initial statements form a race condition.

By using #1 or always@(x_in) you delay the assignment to `temp1 until after x_in is defined.

Much better would be to add a 'load' signal to your counter which picks up the value of x_in when activated.

Also your y_out is delayed by another clock cycle.

Normally a loadable counter would look like:

always@(posedge clk)
begin
   if (load)
      y_out <= x_in;
   else
      y_out <= y_out + 1;   
end
1
votes

Answering your question 1: there is absolutely ne guaranteed order of execution between initial blocks. Verilog simulation starts them in arbitrary unpredictible order. The only way to synchronize are #delays and other wait and delay statements.

Verilog guarantees that execution of any procdeural block, (which includes initial and always blocks) will stop at a wait condition till it gets satisfied.

Verilog also guarantees that all initial blocks start before any always block.

Any signal specified at an alway block sensititivity list play a role of a 'delay' statement, causing the always block to wait till any of the signal values changes. It will continue execution of the block afterwards.

So, answering your second question, always@(x_in) will wait till the value of the signal changes.

so, in your case:

 initial begin    << will start execution at time '0' before any always block
    clk=1'b0;     << change value of clk from 'x' -> '1' 
    x_in=32'd0;   << change value of x_in 'x' -> '0'
    #0            << makes absolutely no sense here. It is a special statement
    #10000        << pauses execution for 10000 time units
    $stop;        << stopps execution
end

while the above initial block yields, the other blocks start execution.

initial begin     << starts execution at time 0, befor or after the block above
    #1 temp=x_in; << pauses for 1 time unit, then assigns temp
end 

The assignment above happens while the first initial block waits #10000.

if you use the always block

always @(x_in)
   temp = x_in;

it will do assignemt when x_in changes and the first initial block starts waiting. This always block will be executed at the same cycle '0' when the signal gets chenged. It is different from the #1 which you used. In your cases the change will happen at cycle '1'.