Wednesday 8 March 2017

digital logic - Curious state transitions in state machine RTL simulation


I have a simple state machine as part of my Verilog module:


localparam State_IDLE = 3'b000,
State_WRITETOLANE1 = 3'b001;


reg [2:0] currentState;
reg [2:0] nextState;

always @(posedge TxByteClk) begin
if( rst ) begin
currentState <= State_IDLE;
end else begin
currentState <= nextState;
end

end

always @(*) begin
nextState = currentState;
case( currentState )
State_IDLE: begin
if( TxSync ) begin
nextState = State_WRITETOLANE1;
end
end

State_WRITETOLANE1: begin
nextState = State_IDLE;
end
endcase
end

TxSync is an input signal. The bizarre behavior I'm seeing is that at the positive edge of the clock when TxSync is high, currentState is set to State_WRITETOLANE1 and as a result nextState is set to State_IDLE. But nextState was never set to State_WRITETOLANE1 in the first place! Why is currentState getting a value that was not even present in nextState? Doesn't the line currentState <= nextState; imply that currentState is the delayed version of nextState?



Answer



I went ahead and made a testbench to see the behavior of the circuit. Please right click the image to see it more clearly.


enter image description here



From my simulation, there is nothing unexpected or strange about the waveform. The state gets correctly initialized by the reset. When TxSync is high the state toggles once every clock cycle. When TxSync is deasserted the state holds a constant value.


I also used a lint checker and there are no major problems with the RTL. I must conclude that the circuit is simulating exactly as specified in the RTL. If you were expecting something different, you should make that more clear, and I will tell you how to change the model.


Some notes on the simulation:



  1. The currentState register latches the value of nextState at the rising edge of TxByteClk

  2. The nextState logic is updated after an infinitesimally small unit of time after the rising edge of TxByteClk (or TxSync), since this is a 0 delay model

  3. The currentState and nextState may appear to change simultaneously, but currentState is updated first


Pitfall: If your testbench updates the TxSync input exactly at the rising clock edge, You will just have a glitch in nextState. Your simulator may remove this glitch, making it look like nextState never entered State_WRITETOLANE1, when in fact it did, just for a very brief moment. This would make it look like currentState latched a value that nextState never had.


Remedy: Don't update the inputs exactly at the rising clock edge. Add some small delay so that the simulation can be more clearly understood. In my case, I updated the input at the falling clock edge. But the update time is arbitrary if you are doing a 0 delay simulation.



No comments:

Post a Comment

arduino - Can I use TI&#39;s cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...