Search code examples
verilogsystem-verilogsynthesis

Setting values in an initial block in Verilog


I think I may be mis-understanding how the initial block works in Verilog.

I have the following bit of code driving hardware sprites:

// horizontal and vertical screen position of letters
logic signed [CORDW-1:0]            spr_x[SPR_CNT];
logic signed [CORDW-1:0]            spr_y;

initial begin
    spr_x[0] = 20;
    spr_x[1] = spr_x[0] + 30;
    spr_x[2] = spr_x[1] + 30;
    spr_x[3] = spr_x[2] + 30;
    spr_x[4] = spr_x[3] + 30;
    
    spr_y = 100;

    ...
end

always_comb begin
    spr_y = 16'd100;

    spr_x[0] = 20;
    spr_x[1] = spr_x[0] + 30;
    spr_x[2] = spr_x[1] + 30;
    spr_x[3] = spr_x[2] + 30;
    //spr_x[4] = spr_x[3] + 30;

    ...
end

genvar m;  // for looping over sprite instances  
generate for (m = 0; m < SPR_CNT; m = m + 1) begin : sprite_gen
    sprite spr0 (
        .i_reset_n(i_reset_n),
        .i_clock(i_pixel_clock),
        .i_spr_y(spr_y),
        .i_spr_x(spr_x[m]),
    );
end endgenerate

I was under the impression that values assigned inside the initial block would stick because they are assigned to logic types which keep their values.

In the example above though my last sprite (index 4) does not display at the correct x position because the spr_x value is not refreshed in always_comb.

I'm surely missing or misunderstanding something here.


Solution

    • Do not use an initial block to drive variables for a synthesis build. Doing so results in unpredictable behavior. Use parameter or localparam to make the assignments instead.

    • The post has multiple drivers (driven in two processes) on spr_x at t=0. Its not clear which process will win.

    • In simulation, the always_comb block gets called at t=0. Its not possible to know which process (initial or always_comb) executes first.

    • Declaring a 2nd variable spr_x_comb to drive spr_x using parameter or localparam, because they are set during elaboration prior to t=0 in simulation.

    • Use variable spr_x_comb to fan into the generate block.

    • Get rid of the assignments to spr_x in the initial block.

    • Generally, do not set values of variables in an initial block for synthesis workflows. Define parameter and localparam statements to make these types of assignments.