1
\$\begingroup\$

This is my state machine code:

module DES_FSM (
    input CLK,
    input Start,
    input Reset,
    input [3:0] Input_Data,
    input [3:0] Next_Round_Data,
    output reg [3:0] Output_Data,
    output reg Complete
);
    reg c;
    //reg [3:0] out;
    reg [5:0] State;
    reg [5:0] Next_State;

    parameter Idle = 5'b00000;
    parameter R1    = 5'b00001;
    parameter R2    = 5'b00010;
    parameter R3    = 5'b00011;
    parameter R4    = 5'b00100;
    parameter R5    = 5'b00101;
    parameter R6    = 5'b00110;
    parameter R7    = 5'b00111;
    parameter R8    = 5'b01000;
    parameter R9    = 5'b01001;
    parameter R10   = 5'b01010;
    parameter R11   = 5'b01011;
    parameter R12   = 5'b01100;
    parameter R13   = 5'b01101;
    parameter R14   = 5'b01110;
    parameter R15   = 5'b01111;
    parameter R16   = 5'b10000;
    parameter Done = 5'b11111;

    //assign Output_Data = out;
    //assign Complete    = c;

    always @(posedge CLK or posedge Reset) begin
        if(Reset)
            State = Idle;
        else
            case (State)
                Idle: if(Start) State = R1;
                R1:     State = R2;
                R2:     State = R3;
                R3:     State = R4;
                R4:     State = R5;
                R5:     State = R6;
                R6:     State = R7;
                R7:     State = R8;
                R8:     State = R9;
                R9:     State = R10;
                R10:        State = R11;
                R11:        State = R12;
                R12:        State = R13;
                R13:        State = R14;
                R14:        State = R15;
                R15:        State = R16;
                R16:        State = Done;
                Done:       State = Idle;
                default: State = 5'bxxxxx;
            endcase
    end

    always @(State) begin
        case (State)
            Idle:   Output_Data = R1;
            R1:     Output_Data = Input_Data;
            R2:     Output_Data = Next_Round_Data;
            R3:     Output_Data = Next_Round_Data;
            R4:     Output_Data = Next_Round_Data;
            R5:     Output_Data = Next_Round_Data;
            R6:     Output_Data = Next_Round_Data;
            R7:     Output_Data = Next_Round_Data;
            R8:     Output_Data = Next_Round_Data;
            R9:     Output_Data = Next_Round_Data;
            R10:        Output_Data = Next_Round_Data;
            R11:        Output_Data = Next_Round_Data;
            R12:        Output_Data = Next_Round_Data;
            R13:        Output_Data = Next_Round_Data;
            R14:        Output_Data = Next_Round_Data;
            R15:        Output_Data = Next_Round_Data;
            R16:        Output_Data = Next_Round_Data;
            Done:       Complete        = 1'b1;
            default: Output_Data = 5'bxxxxx;
        endcase
    end

endmodule

And this is the test bench:

module FSM_Test;
  reg clk, start, reset;
  reg [3:0] in, next_in;
  wire [3:0] out;
  wire complete;

  DES_FSM FSM (clk, start, reset, in, next_in, out, complete);

  initial begin
    clk = 1;
    start = 1;
    reset = 0;
    //#20 reset <= 0;
    in = 4'b0011;
    next_in = 4'b1100;
  end

  always @(clk) begin
    #10 clk <=~ clk;
  end

  initial #200 $stop;
endmodule

I'm using this state machine to count how many rounds have passed in a DES encryption module. I synthesized my design using Altera Quartus II software and simulation using ModelSim Altera.

When I pass the values in my test bench to the design, the output on all rounds is x. Clearly as the design states on the first round it should make Input_Data as the output and on the other rounds Next_Round_Data is the output.

I kinda solved it by either provide a low-high pulse on the Reset or using default: State = Idle; instead of default: State = 5'bxxxxx; since somehow State is unknown at start which will be initialized on the second clock cycle.

Can I get the desired output on start up ? I mean getting the state machine into an initial state on the first clock cycle rather waiting clock cycles for initialization.

EDIT: I had my design based on this example.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Modify your test_bench to toggle reset such that it is high for a couple of clocks at the beginning. \$\endgroup\$
    – rioraxe
    Feb 12 '15 at 2:38
4
\$\begingroup\$

This is exactly why a Reset signal is added to the system. To bring it to an initial known state. There is no way to avoid it when working with actual hardware. As for simulation, you can add an initial block to the design and initialize the state to whatever you want, but it is not synthesizable.

\$\endgroup\$
1
  • \$\begingroup\$ Having a low-high pulse makes sense. Assigning an initial value to the State register gave me some problems. \$\endgroup\$
    – 3bdalla
    Feb 13 '15 at 15:00
2
\$\begingroup\$
  1. You're not using Next_State so I'm not clear why you bother to have it at all. The (recommended) approach would be to do a blocking assignment to Next_State in your combinational always block, and a non-blocking asignment from Next_State to State in your synchronous always block.
  2. You're over-allocating the State and Next_State variables; they only need 5 bits, not 6.
  3. By assigning 5'bxxxx to State as the default case, you're ensuring that if State is ever out of range it always stays that way. Assign a useful value in the default case, presumably either Idle or R1.
  4. You can assign an initial value when you define the State and Next_State variables, e.g. reg [4:0] State = Idle; In order to do so, you will (probably) have to define the parameters first.
\$\endgroup\$
2
\$\begingroup\$

You skipped the reset operation in your test-bench, Reset should go high and some time later go low. If you are targeting for FPGA, you could also put initial State = Idle; in your design. Note that initial only works for simulation and FPGA synthesis, not IC synthesis.

Other issues: Input_Data and Next_Round_Data are missing form the sensitivity list that assign Output_Data. This is inferring complex latching logic in simulation. Most synthesizers will treat is as combination logic. To insure matching behavior, change always @(State) to always @*.

You could also do always @(State or Input_Data or Next_Round_Data) however you should only explicitly list the nets in the sensitivity list for combinational logic if you are limited to the IEEE Std 1364-1995 coding style. IEEE Std 1364-2001 and *-2005 recommend always @*. @* (or equivalent @(*)) manages the sensitively list for the block for you.

Also, when assigning State use non-blocking assignments (<=). Use blocking assignment (=) on your clock driver in the test-bench.

\$\endgroup\$
4
  • \$\begingroup\$ Leaving signals out of sensitivity lists does not generally result in latches being synthesized, but it does cause the simulation to deviate from reality. \$\endgroup\$
    – Dave Tweed
    Feb 11 '15 at 21:51
  • \$\begingroup\$ AFAIK the sensitivity list is meant for simulation only and has no effect on synthesis. Correct me if I am wrong (this is kind of confusing subject..) \$\endgroup\$
    – Eugene Sh.
    Feb 11 '15 at 22:40
  • \$\begingroup\$ Guess my tool set enforce stricter rules. I work in IC design where it is considered a critical bug if RTL simulation does not match gates functionality. I checked with my synthesis lead. He said most synthesizers probably do not look at sensitivity lists for comb logic but the are allowed to; it a matter if implementation choice for the creator of the synthesizer. Best practice is to @* for comb logic to insure matching behavior across simulators and synthesizers. I'll update my answer. \$\endgroup\$
    – Greg
    Feb 12 '15 at 17:45
  • \$\begingroup\$ Sensitivity list has an effect on synthesis. When there are inputs inside always construct but not inside the sensitivity list it generates "inferring latch". And there are some differences on the RTL view, when having an inferring latch it gives some extra latches for the output on the RTL. \$\endgroup\$
    – 3bdalla
    Feb 13 '15 at 15:04

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.