1
\$\begingroup\$

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?

\$\endgroup\$
5
  • \$\begingroup\$ The FSM looks correct. Could you edit the code to be compileable? It just needs the parameter definitions and module statement, but if I compile it I want to compile the same code that you have the problem in. \$\endgroup\$ – travisbartley Jul 22 '13 at 5:04
  • \$\begingroup\$ Is nextState or currentState being driven by any other code not listed here? \$\endgroup\$ – travisbartley Jul 22 '13 at 5:05
  • 1
    \$\begingroup\$ Might help to upload a waveform displaying the relevant signals. \$\endgroup\$ – Tim Jul 22 '13 at 5:19
  • \$\begingroup\$ I added the params. currentState and nextState are being driven by nothing other than what is shown here. I will add a waveform tomorrow when I have access but it is unambiguous, at the posedge currentState changes to a value that nextState has never held. \$\endgroup\$ – ballaw Jul 22 '13 at 5:23
  • \$\begingroup\$ nextState should have been set to State_WRITETOLANE1 as soon as TxSync went high. Do you have a timing diagram that shows this didn't happen? What value are you seeing in nextState before the clock edge? \$\endgroup\$ – The Photon Jul 22 '13 at 5:27
4
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ That is indeed the answer. Thanks!. but why is the simulator doing this? It' worked with identical state machines? Shouldn't simulators react as if everything happened at the rising edge and not allow for glitches? \$\endgroup\$ – ballaw Jul 22 '13 at 16:18
  • \$\begingroup\$ The state register gets updated only at the rising edge of the clock. But remember that you're not just modeling the state, which is sequential, but you are also modeling the state reload logic, which is combinatorial. These two components are the first and second always blocks, respectively. So for the sequential part, it doesn't matter at what phase of the clock cycle you change the input. But the combinatorial part does depend on when the input changes, as it will update immediately. If the input changes at the posedge clock, the combi part will update twice too fast to see it on the sim. \$\endgroup\$ – travisbartley Jul 23 '13 at 1:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.