Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

System Verilog: Can´t change value of a "struct" variable

Hi,

I´m newbie on Verilog, actually also in System Verilog, but worked long time ago with VHDL and C++ languages.

I used a template of a Moore state machine from ALTERA for Verilog, and performed some changes in order to start the learning.

However, during simulation, I can´t see any change at both the variables currentstate.level_main and currentstate.level_sub. I took the care to perform reset during simulation.

module moore_mac
(
    input    clk, data_in, reset,
    output reg  data_out
);
    reg  sub_state3, state ;
    parameter   S0   = 3'b000, S1   = 3'b001, S2   = 3'b010, S3   = 3'b011 ;
    parameter   S3_0 = 3'b100, S3_1 = 3'b101, S3_2 = 3'b110                ;
 
    typedef enum { SM0  , SM1  , SM2  , SM3   } STATE_MACHINE   ;
    typedef enum { SM0_S, SM1_S, SM2_S, SM3_S } STATE_MACHINE_S ;
    
    typedef struct { 
       reg  Level_main ;
       reg  Level_sub ;
    } FSM ;
    FSM     CurrentState ;
    
        
        
    // Determine the next state
    always @ ( posedge clk or posedge reset ) 
        begin
            if (reset)
                begin 
                    state         <= S1   ;
                    sub_state3    <= S3_0 ;
                    CurrentState.Level_main <= S0   ;
                    CurrentState.Level_sub  <= S3_0 ;                    
                end
            else
                case (state)
                    S0:
                                     state            <= S1;
                    S1:
                        if (data_in) state         <= S1;
                        else         state         <= S2; 
                    S2:
                        if (data_in) state         <= S1;
                        else         state         <= S3;
                    S3:        
                                     state <= next_state ( sub_state3 ) ;
                endcase
        end
    // Output depends only on the current state
    always @ (state) 
        begin
            case (state)
                S0:
                    data_out = S0 ;
                S1:
                    data_out = S1 ;
                S2:
                    data_out = S2 ;
                S3:
                    data_out = S3 ;
                default:
                    data_out = S0 ;
            endcase
        end
        
//  ******************************************************* 
//  Gets next state, by assessing corresponding sub_state
//  ******************************************************* 
    function  next_state  ;
        input reg  valSubstateBefore  ;
              reg  valSubstateAfter   ;
              
        if ( valSubstateBefore < S3_2 )
            begin
                valSubstateAfter = valSubstateBefore + 1 ;
                state = state ;
            end
        else
            begin
                valSubstateAfter = S3_0 ;
                state = S0 ;
            end
        sub_state3 = valSubstateAfter     ;
        next_state = state ;        
    endfunction
//  ******************************************************* 
endmodule

Thanks in advance.

Andre

23 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Tricky,

    Thanks for the tip, I did the change based on your suggestion and the code seems now cleanest, but the function next_state isn´t still working as expected, and I presume that compiler is creating extra registers which could avoid the proper functioning. I´m putting bellow the last version of the code, and also attached the .vcd testbench generated by Simulation Waveform editor of QuartusII.

    Just to review the need: The basic idea is to create of a function that once called, increments a sub-state at each clock event, and keep itself in the main state while not reached the last sub-state; on other words, it´s a kind of run sub states at a bottom layer. Can you see something clearly wrong on this program regarding to the fundamentals of coding on Verilog/SV ?

    parameter ST_SIZE    =    4 ;
    parameter ST_START    =    4'b0 ;
    parameter ST_STEP    =    4'b1 ;
        
    module moore_mac
    (
        input    clk, data_in, reset,
        output reg  data_out
    );
    //******************************* Parameter definitions  
        
        parameter  S0   =     ST_START         ;
        parameter  S1   = S0    +    ST_STEP ;
        parameter  S2   = S1    +    ST_STEP ;
        parameter  S3   = S2    +    ST_STEP ;
        parameter  S4   = S3    +     ST_STEP ;
        parameter  S5   = S4    +     ST_STEP ;
        parameter  S6   = S5    +     ST_STEP ;
        parameter  S7   = S6    +     ST_STEP ;
        parameter  S8   = S7    +     ST_STEP ;
        parameter  S9   = S8    +     ST_STEP ;
        
        parameter   S5_3 =     ST_START         ;
        parameter   S5_2 = S5_3    +     ST_STEP ;
        parameter   S5_1 = S5_2    +     ST_STEP ;    
        parameter   S5_0 = S5_1    +     ST_STEP ;    
      
    //******************************* Type declarations  
        
        typedef struct packed { 
           logic  Level_main    ;  // Current state     ( main level )
           logic  Level_sub     ;  // Target sub-state  ( 1 depth bellow )
           logic  Level_subcurr ;  // Current sub-state ( 1 depth bellow )
        } FSM ;
           
    //******************************* Varable declarations 
        reg res  = 0      ;
        reg ires = 0    ;
        
        FSM                 StateMachine         ;  
        
    //********************************** Determine the next state
        
        always @ ( posedge clk )
        begin
          ires     <= reset ;
          res     <= ires ;
        end
        
        always @ ( posedge clk or posedge res ) 
            begin
                if (res)
                    begin 
                        StateMachine.Level_main <= S0   ;
                    end
                else
                    begin
                        case (StateMachine.Level_main)
                            S0:
                                                 StateMachine.Level_main     <= S1;
                            S1:
                                if (data_in)     StateMachine.Level_main     <= S1;
                                else             StateMachine.Level_main     <= S2; 
                            S2:
                                if (data_in)     StateMachine.Level_main     <= S1;
                                else             StateMachine.Level_main     <= S3;
                            S3:
                                                StateMachine.Level_main      <= S4;
     
                            S4:
                    begin
                                                StateMachine.Level_main     <= S5;
                                                StateMachine.Level_sub      <= S5_0;
                                                StateMachine.Level_subcurr  <= S5_3;
                                    end
                                                                       
                            S5:    
                                                StateMachine        <= next_state ( 
                                                StateMachine.Level_main        , 
                                                StateMachine.Level_sub         ,
                                                StateMachine.Level_subcurr
                                                ) ;     
                            S6:
                                                StateMachine.Level_main     <= S7;
                            S7:
                                                StateMachine.Level_main     <= S8;    
                            S8:
                                                StateMachine.Level_main     <= S9;                    
                            S9:
                                                StateMachine.Level_main     <= S0;                                                           
                            default:
                            StateMachine.Level_main     <= S0;
                        endcase
                    end
            end
    //********************************** Determine the output value
        always @ ( posedge clk ) 
            begin
                case ( StateMachine.Level_main )
                    S0:
                        data_out <= S0 ;
                    S1:
                        data_out <= S1 ;
                    S2:
                        data_out <= S2 ;
                    S3:
                        data_out <= S3 ;
                    S4:
                        data_out <= S4 ;
                    S5:
                        data_out <= S5 ;
                    S6:
                        data_out <= S6 ;
                    S7:
                        data_out <= S7 ;      
                    S8:
                        data_out <= S8 ;    
                    S9:
                        data_out <= S9 ;                                                                                               
                    default:
                        data_out <= S0 ;
                endcase
            end
            
    //  ********************************************************************* 
    //  Increments sub-state and get out to next main state after completion
    //  ********************************************************************* 
        function FSM next_state( 
                input logic  valStateBefore        ,         
                input logic  valSubstateBefore     ,    
                input logic  valSubstateCurrent     
                );
                     
            FSM next_state_return ;   
              
             if ( valSubstateCurrent < valSubstateBefore )  // increments sub-state, but keep main state unchanged
                begin  
                    next_state_return.Level_main    = valStateBefore                   ;
                    next_state_return.Level_sub    = valSubstateBefore                ;
                    next_state_return.Level_subcurr    = valSubstateCurrent + ST_STEP     ; 
                end
            else                            // increments main state
                begin
                    next_state_return.Level_main    = valStateBefore + ST_STEP        ;
                    next_state_return.Level_sub    = valSubstateBefore                ;
                    next_state_return.Level_subcurr    = valSubstateCurrent             ;
                end        
                
            return next_state_return ;
                
        endfunction
    endmodule

    Whatever change I do, nothing happens with the current substate, as bellow:

    http://www.alteraforum.com/forum/attachment.php?attachmentid=10231&stc=1

    Please note that this code has only meant to be an opportunity to have the first contact with the language, it may contain other problems, but the focus right now is the unexpected behavior of the function.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Please - try modelsim. It will REALLY help you debug your code.

    Trying to debug at the gate level is really not going to help here.

    The synthesisor is only doing what you've told it. There is likely a bug in your Verilog, that I dont have time to look at. This should be your job.

    My review - the code is still overly complicated. All you need is a counter in S5. The counter counts while you're in S5, then when you reach the correct value, you move to S6.