As I was working on a SystemVerilog based FPGA design, I came across a situation where I had to compute the sum of an array of 4 elements on a clock edge. I was able to do that using a for loop with non blocking assign statements.
The design synthesized successfully on Quartus 15.0 but when I tried to run the simulations using the same RTL on Modelsim Altera the results were unexpected. I have written a sample code to illustrate the same.
module schedule;
logic [7:0] abc [0:3];
logic [7:0] sum=0;
logic clk=0;
always begin
#5.0ns clk <= ~clk;
end
initial begin
abc = '{1,3,5,6};
end
initial @(posedge clk) begin
for(int i = 0; i <= 3;i++ ) begin
sum <= sum + abc[i];
end
end
initial
$monitor("Sum is %d",sum);
endmodule
This image shows the simulation results.
In this sample code, sum is computed using non-blocking assignments. It was intended to have a value of (1+3+5+6)=15 on the first posedge of clk; which I have observed in original hardware. But in simulation the result was 6 at the posedge of clk(which is abc[3]). Since the systemverilog simulators schedule the assignments for non-blocking statements, I believe 4 instances of sum are created viz.
sum <= sum + abc[0];
sum <= sum + abc[1];
sum <= sum + abc[2];
sum <= sum + abc[3];
As all the scheduled assignments happen simultaneously, may be the last instance updated sum and we have a value of sum <= 0 + 6. Please correct me if I'm wrong.
Now my question is how do I make the simulator schedule these assignments sequentially so that I get a value of 15 even in simulation? Since blocking assignments are not an option in synthesis, I cant find any way to keep the RTL consistent. Thanks.