verilogsystem-verilogledfsm

How to stay in the same FSM state after input turns zero?


I am trying to make an FSM that turns on different LEDs on an LED matrix depending on the button pressed. However, the LED doesn't stay on, and after releasing the button, the first LED turns on again. Here is the code:

module OneLed( input logic clk, reset, input logic [1:0] button, 
           output logic [7:0] rows, 
           output logic shcp, stcp, mr, oe, ds); //The LED matrix has 3 74hc595 shift registers below it
      
      logic [7:0] [23:0] in;
      logic [1:0] butreg; // thought a register would remember the button input
      assign butreg = button; 

      //FSM
      typedef enum logic [1:0] {S0, S1, S2} statetype;
      statetype state , nextstate;

     //state register
     always_ff @(posedge clk, posedge reset)
           if (reset) state <= S0;
           else state <= nextstate;

     //next state logic 
           always_comb
                 case(butreg)
                     S0: if (2'b01) nextstate = S1;
                         else if (2'b10) nextstate = S2;
                         else nextstate = S0;
    
                     S1: if (2'b01) nextstate = S2;
                         else if (2'b10) nextstate = S0;
                         else nextstate = S1;

                     S2: if (2'b01) nextstate = S0;
                         else if (2'b10) nextstate = S1;
                         else nextstate = S2;     
                     default: nextstate = S0;
           endcase 

    //output logic 
    always_comb
           begin
               if (state == S0)
                  in [0] = 24'b10000000_00000000_00000000;
               else if (state == S1)
                  in [0] = 24'b00000000_10000000_00000000;
               else  if (state == S2)        
                  in[0] =  24'b00000000_00000000_10000000;
   end         

   led LED ( clk, in , rows, shcp, stcp, mr, oe, ds); // this module works fine
endmodule   

Solution

  • assign butreg = button; 
    

    This statement treats butreg as a wire, that is connected directly to your input signal button.

    If you are looking to latch the value of button into the register butreg, you would need to use a always block and trigger at the appropriate event (posedge clk or * or some other condition.

    For example, instead of the above assign, you may have

    always @(posedge clk) begin
      if (button == 2'b00) begin
        butreg <= butreg;
      end
      else begin
        butreg <= button;
      end
    end