According to me Check following line might be hanging .
@ (negedge ifc.spi_cs );
Once ifc.spi_cs is equal to zero it might come out of while loop but to come out @ (negedge ifc.spi_cs ) it requires ifc.spi_cs to encounter a negedge not level sensitive zero.
Actually I modified the code and put $display statements in while statement. During the simulation I can see that infitie loop occurs because of the while statement. My code enters in while statement and stays there forever
class Receiver ;
...
task dutOutMonitor ();
@ (posedge ifc.wr_doing )
@ (posedge ifc.spi_cs )
while (ifc.spi_cs == 1'b1 )
begin
@ (posedge ifc.spi_sck )
$display("Inside while: the value of ifc.spi_cs is %d", ifc.spi_cs);
end
@ (negedge ifc.spi_cs )
this.ReceiveBox.put (dataIn );
return;
endtask
endclass
program execTest ();
initial
begin: WRITE
genObj.CONFIG();
genObj.randomize();
genObj.WRITE();
receivObj.dutOutMonitor();
end
endprogram
After simulation the simulator always prints this line:
Inside while: the value of ifc.spi_cs is 1
Inside while: the value of ifc.spi_cs is 1
Try putting display statement immediately i.e. before @ (negedge ifc.spi_cs ) after while loop and check . From this we will know whether it has exited while loop or still in while loop.
Sorry i also checked that there is @ (posedge ifc.spi_sck ) inside while loop . So this simulator run waits until it gets posedge then after that it immediately checks while loop condition which if equal to 1 at that particular movement then it may hang. so can you check this condition . i think due to this it getting stuck in while loop
Put the display before clock edge and see if spi_cs is 0 or not.
while (ifc.spi_cs == 1'b1 )
begin
$display("Inside while: the value of ifc.spi_cs is %d", ifc.spi_cs);
@ (posedge ifc.spi_sck )
end
Also I think CS and synchronized with posedge of CLK thats why Delay is not captured by simulation.
Solution1 :
while (ifc.spi_cs == 1'b1 )
begin
$display("Inside while: the value of ifc.spi_cs is %d", ifc.spi_cs);
@ (negedge ifc.spi_sck )
end[
Solution2 :
while (ifc.spi_cs == 1'b1 )
begin
$display("Inside while: the value of ifc.spi_cs is %d", ifc.spi_cs);
@ (posedge ifc.spi_sck )
#0 //This will remove delta delay issue if its there.
end[
I have added $display statements in the code like the below:
class Receiver ;
...
task dutOutMonitor ();
@ (posedge ifc.wr_doing )
@ (posedge ifc.spi_cs )
while (ifc.spi_cs == 1'b1 )
begin
$display ("1. Value of spi_cs is %d", ifc.spi_cs);
@ (posedge ifc.spi_sck )
$display ("2. Value of spi_cs is %d", ifc.spi_cs);
end
$display ("3. Value of spi_cs is %d", ifc.spi_cs);
@ (negedge ifc.spi_cs )
$display ("4. Value of spi_cs is %d", ifc.spi_cs);
endtask
endclass
program execTest ();
initial
begin: WRITE
genObj.CONFIG();
genObj.randomize();
genObj.WRITE();
receivObj.dutOutMonitor();
end
endprogram
And this is the output that I am getting
===== INFO: Starting WRITE
Task: CONFIG
Task: WRITE
TASK: dutOutMonitor
1. Value of spi_cs is 1
2. Value of spi_cs is 1
1. Value of spi_cs is 1
2. Value of spi_cs is 1
1. Value of spi_cs is 1
2. Value of spi_cs is 1
1. Value of spi_cs is 1
... (all the same sequence)
I have a feeling, that when entering into while statement, it doesn’t check the external signals - ifc.spi_cs. So to get out from the while, I need to modify the ifc.spi_cs signal inside while cycle.
It’s most likely due to a race condition between spi_sck and spi_cs. You are essentially evaluating spi_cs after the @(posedge spi_sck). If it is 1, then it waits for the next @(posedge spi_sck). If spi_sck doesn’t have a posedge after spi_cs is 0, then you will be stuck waiting for the nest @(posedge spi_sck), which when that occurs, spi_cs is back to the value of 1.
I agree with your statement! Truly, the code waits for @(posedge spi_sck) signal for ages.
Thank you very much for your explanation!
I think I need to try avoid using while statements, because of high chance of having race conditions. Could someone share his experience on using the while statements? and how you usually create iterations in initial blocks
After looking into Waveform, @cgales is correct when cs is low clk is not there.so it obvious it will stuck into while loop.
workaround - you can have one more clock which is one clock advance to spi_clk,use this advance clk so that last posedge of adv.clock will detect the cs==0 condition and it will comeout from loop.
However its just a workaround not the good practice ;)