UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Participant jpnaude
Participant
9,902 Views
Registered: ‎03-18-2009

State machine synthesis problems

Jump to solution

Hi there

 

I've been struggling with a design containing 3 state machines (Moore) working together to form a dynamic memory map. In behavioral simulation the simulation works perfectly but in structural simulation the design does not work. We've also rewrote the design from scratch and used the ISE Moore state machine templates as the basis of the 3 state machines. Our synthesis report does not give anything suspicious as far as I can see. We've checked in both XST and Synplify and both of them give a netlist which behaves different from the behavioral model (the XST netlist also behaves different compared to the Synplify netlist). I've attached the XST synthesis report which might be usefull, and I will give the code for one of our state machines below to see if anyone can find something fundementally wrong in the way its been done. 

 

Any help would be greatly appreciated.

Thanks

Jaco

 

 

 

State machine - In structural simulation the state machine gets stuck in the following state: st_init_response

=============================================================================

 

 ENTITY DMM_SPLITTER IS
    GENERIC(
      G_DATA_WIDTH : natural := 32;
      G_ADDR_WIDTH : natural := 24
   );
   PORT(
      S_DATA      : IN     transmit_bus;   --! Data received from a splitter or interface feeding this splitter.
      S_RESPONSE  : OUT    response_bus;   --! Data sent to a splitter or interface feeding this splitter.
      M0_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M0_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      M1_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M1_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      CLK         : IN     std_logic;      --! Clock input.
      RESET_N     : IN     std_logic       --! Active-low reset input.
   );

-- Declarations

END DMM_SPLITTER ;
-- hds interface_end
-- hds interface_end

--! @brief Architure definition DDM_SPLITTER
--! @details This architecture definition should work on any device from any vendor.
architecture RTL of DMM_SPLITTER is

   type state_type is (st_startup, st_init, st_init_m0, st_init_m1, st_init_response, st_ready, st_request_m0, st_request_m1, st_request_idle, st_response_m0, st_response_m1, st_error);
   signal state, next_state : state_type;
    
    signal new_state_valid_i             : std_logic := '0';
    signal m0_size            : integer := 0;
    signal m1_size            : integer := 0;    
    signal s_data_i        : transmit_bus := ((others => '0'), (others => '0'), '0', '0');
    signal s_response_i    : response_bus := ((others => '0'), '0');        
    signal m0_data_i        : transmit_bus := ((others => '0'), (others => '0'), '0', '0');
    signal m0_response_i    : response_bus := ((others => '0'), '0');        
    signal m1_data_i        : transmit_bus := ((others => '0'), (others => '0'), '0', '0');
    signal m1_response_i    : response_bus := ((others => '0'), '0');    
    signal tmp_addr  : integer := 0;        

begin

   SYNC_PROC: process (CLK)
   begin
      if (CLK'event and CLK = '1') then
         if (RESET_N = '0') then
            state <= st_startup;
            S_RESPONSE.DATA <= (others => '0');
            S_RESPONSE.DVAL <= '0';
            M0_DATA.DATA <= (others => '0');
            M0_DATA.ADDR <= (others => '0');
            M0_DATA.DVAL <= '0';
            M0_DATA.RNW <= '0';
            M1_DATA.DATA <= (others => '0');
            M1_DATA.ADDR <= (others => '0');
            M1_DATA.DVAL <= '0';
            M1_DATA.RNW <= '0';                
         else
            -- This will generate a valid pulse for new states.
            if next_state = state then
                new_state_valid_i <= '0';
            else
                new_state_valid_i <= '1';                
            end if;
            -- Sets the current state equal to the next_state.
            state <= next_state;            
            -- Assign other outputs to internal signals.
                        S_RESPONSE <= s_response_i;                
            M0_DATA <= m0_data_i;    
            M1_DATA <= m1_data_i;                    
         end if;        
      end if;
   end process;
 
   OUTPUT_DECODE: process (state)
   begin
      -- Insert statements to decode internal output signals
    if state = st_init_m0 then
            m0_data_i.DATA <= (others => '1');
            m0_data_i.ADDR <= (others => '1');
            m0_data_i.DVAL <= new_state_valid_i;
            m0_data_i.RNW  <= '0';            
            m1_data_i.DATA <= (others => '0');
            m1_data_i.ADDR <= (others => '0');
            m1_data_i.DVAL <= '0';
            m1_data_i.RNW  <= '0';                
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';            
        elsif state = st_init_m1 then
            m0_data_i.DATA <= (others => '0');
            m0_data_i.ADDR <= (others => '0');
            m0_data_i.DVAL <= '0';
            m0_data_i.RNW  <= '0';
            m1_data_i.DATA <= (others => '1');
            m1_data_i.ADDR <= (others => '1');
            m1_data_i.DVAL <= new_state_valid_i;
            m1_data_i.RNW  <= '0';            
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';    
        elsif state = st_init_response then
              m0_data_i.DATA <= (others => '0');
              m0_data_i.ADDR <= (others => '0');
              m0_data_i.DVAL <= '0';
              m0_data_i.RNW  <= '0';
              m1_data_i.DATA <= (others => '0');
              m1_data_i.ADDR <= (others => '0');
              m1_data_i.DVAL <= '0';
              m1_data_i.RNW  <= '0';        
              s_response_i.DATA <= std_logic_vector(conv_unsigned(m0_size + m1_size, G_DATA_WIDTH));
              s_response_i.DVAL <= new_state_valid_i;                    
        elsif state = st_ready  then
            m0_data_i.DATA <= (others => '0');
            m0_data_i.ADDR <= (others => '0');
            m0_data_i.DVAL <= '0';
            m0_data_i.RNW  <= '0';
            m1_data_i.DATA <= (others => '0');
            m1_data_i.ADDR <= (others => '0');
            m1_data_i.DVAL <= '0';
            m1_data_i.RNW  <= '0';        
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';                
        elsif state = st_request_idle then
            m0_data_i.DATA <= (others => '0');
            m0_data_i.ADDR <= (others => '0');
            m0_data_i.DVAL <= '0';
            m0_data_i.RNW  <= '0';
            m1_data_i.DATA <= (others => '0');
            m1_data_i.ADDR <= (others => '0');
            m1_data_i.DVAL <= '0';
            m1_data_i.RNW  <= '0';        
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';                
        elsif state = st_request_m0 then
            m0_data_i.DATA <= s_data_i.DATA;
              m0_data_i.ADDR <= s_data_i.ADDR;            
            m0_data_i.DVAL <= new_state_valid_i;
            m0_data_i.RNW  <= s_data_i.RNW;
            m1_data_i.DATA <= (others => '0');
            m1_data_i.ADDR <= (others => '0');
            m1_data_i.DVAL <= '0';
            m1_data_i.RNW  <= '0';        
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';                    
        elsif state = st_request_m1 then
            m0_data_i.DATA <= (others => '0');
            m0_data_i.ADDR <= (others => '0');
            m0_data_i.DVAL <= '0';
            m0_data_i.RNW  <= '0';
            m1_data_i.DATA <= s_data_i.DATA;
              -- Subtract m0_size from address to compensate for size of first leaf node.
              m1_data_i.ADDR <= std_logic_vector(conv_unsigned(tmp_addr,G_ADDR_WIDTH));        
            m1_data_i.DVAL <= new_state_valid_i;
            m1_data_i.RNW  <= s_data_i.RNW;    
            s_response_i.DATA <= (others => '0');
            s_response_i.DVAL <= '0';        
        elsif state = st_response_m0 then
              m0_data_i.DATA <= (others => '0');
              m0_data_i.ADDR <= (others => '0');
              m0_data_i.DVAL <= '0';
              m0_data_i.RNW  <= '0';
              m1_data_i.DATA <= (others => '0');
              m1_data_i.ADDR <= (others => '0');
              m1_data_i.DVAL <= '0';
              m1_data_i.RNW  <= '0';                
              s_response_i.DATA <= m0_response_i.DATA ;
              s_response_i.DVAL <= m0_response_i.DVAL;                                            
        elsif state = st_response_m1 then
              m0_data_i.DATA <= (others => '0');
              m0_data_i.ADDR <= (others => '0');
              m0_data_i.DVAL <= '0';
              m0_data_i.RNW  <= '0';
              m0_data_i.DATA <= (others => '0');
              m0_data_i.ADDR <= (others => '0');
              m0_data_i.DVAL <= '0';
              m0_data_i.RNW  <= '0';        
              s_response_i.DATA <= m1_response_i.DATA ;
              s_response_i.DVAL <= m1_response_i.DVAL;        
        elsif state = st_error then    
            m0_data_i.DATA <= (others => '0');
            m0_data_i.ADDR <= (others => '0');
            m0_data_i.DVAL <= '0';
            m0_data_i.RNW  <= '0';
            m1_data_i.DATA <= (others => '0');
            m1_data_i.ADDR <= (others => '0');
            m1_data_i.DVAL <= '0';
            m1_data_i.RNW  <= '0';    
            s_response_i.DATA <= error_code;
            s_response_i.DVAL <= new_state_valid_i;
      end if;
   end process;
 
   NEXT_STATE_DECODE: process (state, new_state_valid_i, RESET_N, S_DATA.DVAL, M0_RESPONSE.DVAL, M1_RESPONSE.DVAL)
   begin
      -- Declare default state for next_state to avoid latches
      next_state <= state;  -- Default is to stay in current state
      case (state) is
         when st_startup =>
            if RESET_N = '1' then
               next_state <= st_init;
            else
               next_state <= st_startup;
            end if;
         when st_init =>
            if S_DATA.DVAL = '1' then
                    next_state <= st_init_m0;                
            end if;
         when st_init_m0 =>
            if M0_RESPONSE.DVAL = '1' then
                m0_size <= conv_integer(unsigned(M0_RESPONSE.DATA(15 downto 0)));
                m0_response_i.DATA <= M0_RESPONSE.DATA;
                m0_response_i.DVAL <= M0_RESPONSE.DVAL;                    
                next_state <= st_init_m1;    
            end if;
         when st_init_m1 =>            
            if M1_RESPONSE.DVAL = '1' then                
                m1_size <= conv_integer(unsigned(M1_RESPONSE.DATA(15 downto 0)));
                m1_response_i.DATA <= M1_RESPONSE.DATA;
                m1_response_i.DVAL <= M1_RESPONSE.DVAL;                            
                next_state <= st_init_response;    
            end if;    
        when st_init_response =>
                  next_state <= st_ready;
        when st_ready =>
            if (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) < conv_unsigned(m0_size,G_ADDR_WIDTH))) then
                 s_data_i <= S_DATA;            
                next_state <= st_request_m0;            
            elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m0_size,G_ADDR_WIDTH)) and (unsigned(S_DATA.ADDR) < conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then
                s_data_i <= S_DATA;
                 tmp_addr <= conv_integer(unsigned(S_DATA.ADDR)) - m0_size;          
                next_state <= st_request_m1;                    
            elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then                
                -- The received address is too big for this splitter. Something went wrong upstream in the DMM. Go into error state.
                next_state <= st_error;
            else
                next_state <= st_ready;
            end if;
        when st_request_m0 =>
              next_state <= st_request_idle;    
          when st_request_m1 =>
            next_state <= st_request_idle;            
          when st_request_idle =>
            if M0_RESPONSE.DVAL = '1' then
                  next_state <= st_response_m0;            
                  m0_response_i.DATA <= M0_RESPONSE.DATA;
                  m0_response_i.DVAL <= M0_RESPONSE.DVAL;                                                  
            elsif M1_RESPONSE.DVAL = '1' then                
                 next_state <= st_response_m1;
                  m1_response_i.DATA <= M1_RESPONSE.DATA;
                  m1_response_i.DVAL <= M1_RESPONSE.DVAL;                              
            else
                  next_state <= st_request_idle;
            end if;    
        when st_response_m0 =>                
            next_state <= st_ready;            
        when st_response_m1 =>                
            next_state <= st_ready;                          
        when st_error =>                
            next_state <= st_ready;
        when others =>
            next_state <= st_ready;
      end case;      
   end process;

end RTL;

 

 

 

 

 

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
Participant jpnaude
Participant
12,112 Views
Registered: ‎03-18-2009

Re: State machine synthesis problems

Jump to solution

And now for the working version:

 

 

 

-
ENTITY DMM_SPLITTER IS
    GENERIC(
      G_DATA_WIDTH : natural := 32;
      G_ADDR_WIDTH : natural := 24
   );
   PORT(
      S_DATA      : IN     transmit_bus;   --! Data received from a splitter or interface feeding this splitter.
      S_RESPONSE  : OUT    response_bus;   --! Data sent to a splitter or interface feeding this splitter.
      M0_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M0_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      M1_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M1_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      CLK         : IN     std_logic;      --! Clock input.
      RESET_N     : IN     std_logic       --! Active-low reset input.
   );

-- Declarations

END DMM_SPLITTER ;
-- hds interface_end
-- hds interface_end

--! @brief Architure definition DDM_SPLITTER
--! @details This architecture definition should work on any device from any vendor.
architecture RTL of DMM_SPLITTER is

   type state_type is (st_startup, st_init, st_init_m0, st_init_m1, st_ready, st_request_m0, st_request_m1, st_request_idle);
   signal state : state_type;
   
    signal m0_size            : integer := 0;
    signal m1_size            : integer := 0;           

begin

   SYNC_PROC: process (CLK, RESET_N)
   begin
      if (CLK'event and CLK = '1') then
         if (RESET_N = '0') then
            state <= st_startup;
                        S_RESPONSE <= ((others => '0'),'0');
                        M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                        M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                                   
         else
                        -- This will generate a valid pulse for new states.             
           case (state) is
                when st_startup =>
                  if RESET_N = '1' then
                      state <= st_init;
                  else
                      state <= st_startup;
                  end if;
                when st_init =>
                  if S_DATA.DVAL = '1' then
                                     state <= st_init_m0;
                                     M0_DATA <= ((others => '0'), (others => '0'), '1', '0');               
                  end if;
                when st_init_m0 =>
                              if M0_RESPONSE.DVAL = '1' then
                                     m0_size <= conv_integer(unsigned(M0_RESPONSE.DATA(15 downto 0)));       
                                     M1_DATA <= ((others => '0'), (others => '0'), '1', '0');   
                                     state <= st_init_m1;   
                                 else
                                     M0_DATA <= ((others => '0'), (others => '0'), '0', '0');               
                              end if;                            
                when st_init_m1 =>           
                              if M1_RESPONSE.DVAL = '1' then               
                                     m1_size <= conv_integer(unsigned(M1_RESPONSE.DATA(15 downto 0)));           
                                     S_RESPONSE <= (std_logic_vector(conv_unsigned(m0_size + conv_integer(unsigned(M1_RESPONSE.DATA(15 downto 0))), G_DATA_WIDTH)), '1');       
                                     state <= st_ready;   
                                 else
                                     M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                                               
                              end if;                             
                         when st_ready =>
                             S_RESPONSE <= ((others => '0'), '0');
                             M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                             M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                            
                                if (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) < conv_unsigned(m0_size,G_ADDR_WIDTH))) then
                        M0_DATA <= S_DATA;           
                                       state <= st_request_m0;           
                                elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m0_size,G_ADDR_WIDTH)) and (unsigned(S_DATA.ADDR) < conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then
                        M1_DATA <= S_DATA;
                        M1_DATA.ADDR <= std_logic_vector(conv_unsigned(conv_integer(unsigned(S_DATA.ADDR)) - m0_size,G_ADDR_WIDTH));       
                                       state <= st_request_m1;                   
                                elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then               
                                       -- The received address is too big for this splitter. Something went wrong upstream in the DMM. Go into error state.
                                 S_RESPONSE <= (error_code, '1');
                                end if;
                         when st_request_m0 =>
                   if M0_RESPONSE.DVAL = '1' then
                       S_RESPONSE <= M0_RESPONSE;                    
                       state <= st_ready;           
                   else
                       M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                       state <= st_request_m0;
                   end if;
                when st_request_m1 =>
                   if M1_RESPONSE.DVAL = '1' then
                       S_RESPONSE <= M1_RESPONSE;                    
                       state <= st_ready;           
                   else
                       M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                       state <= st_request_m1;
                   end if;                              
                when others =>
                    state <= st_ready;
                end case;                         
         end if;       
      end if;
   end process;
    
end RTL;
 

0 Kudos
5 Replies
Historian
Historian
9,887 Views
Registered: ‎02-25-2008

Re: State machine synthesis problems

Jump to solution

Consider rewriting the whole mess as a single synchronous process.

 

You might have noticed in your synthesis report that you've got a ton of latches. That's the first sign of failure in the two- or three-process description.  Also, the various INFO:Xst:2371 - HDL Advisor notes are useful indeed.

 

Basically -- the two- and three-process state machines are academic exercises, fraught with problems and utterly impossible to maintain. Nobody who makes their living doing FPGAs implements a state machine in this manner. The people who write the textbooks that advocate this style really should consider another line of work. Really.

 

-a

 

 

----------------------------Yes, I do this for a living.
Xilinx Employee
Xilinx Employee
9,885 Views
Registered: ‎08-13-2007

Re: State machine synthesis problems

Jump to solution

Note of steadfast agreement (personally not officially as a Xilinx position).

 

bt

0 Kudos
Participant jpnaude
Participant
9,851 Views
Registered: ‎03-18-2009

Re: State machine synthesis problems

Jump to solution

Hi

 

Thanks for the responses. Interesting opinions that you gave, thanks. I'll need to get rid of those latches I agree.

 

Lately I've heard so many opinions on the best way to write a VHDL state machine and it seems like everyone has their own opinion (or at least where I work). Thus I decided to use the state machine templates found in the ISE Language Templates (which basically has a Moore and a Meally template) since synthesis tools (XST in our case) must surely find a specific way or writing a state machine as the optimal solution and thus produce the best synthesized result. One would think that the examples found in the ISE Language Templates will do exactly this, but after both of your posts it seems like that's not true.

 

Thanks again for the responses.

I'll have a look at my code,

Cheers

Jaco

 

 

0 Kudos
Participant jpnaude
Participant
12,113 Views
Registered: ‎03-18-2009

Re: State machine synthesis problems

Jump to solution

And now for the working version:

 

 

 

-
ENTITY DMM_SPLITTER IS
    GENERIC(
      G_DATA_WIDTH : natural := 32;
      G_ADDR_WIDTH : natural := 24
   );
   PORT(
      S_DATA      : IN     transmit_bus;   --! Data received from a splitter or interface feeding this splitter.
      S_RESPONSE  : OUT    response_bus;   --! Data sent to a splitter or interface feeding this splitter.
      M0_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M0_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      M1_DATA     : OUT    transmit_bus;   --! Data sent from a leaf node which is fed by this splitter.
      M1_RESPONSE : IN     response_bus;   --! Data received from a leaf node which is fed by this splitter.
      CLK         : IN     std_logic;      --! Clock input.
      RESET_N     : IN     std_logic       --! Active-low reset input.
   );

-- Declarations

END DMM_SPLITTER ;
-- hds interface_end
-- hds interface_end

--! @brief Architure definition DDM_SPLITTER
--! @details This architecture definition should work on any device from any vendor.
architecture RTL of DMM_SPLITTER is

   type state_type is (st_startup, st_init, st_init_m0, st_init_m1, st_ready, st_request_m0, st_request_m1, st_request_idle);
   signal state : state_type;
   
    signal m0_size            : integer := 0;
    signal m1_size            : integer := 0;           

begin

   SYNC_PROC: process (CLK, RESET_N)
   begin
      if (CLK'event and CLK = '1') then
         if (RESET_N = '0') then
            state <= st_startup;
                        S_RESPONSE <= ((others => '0'),'0');
                        M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                        M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                                   
         else
                        -- This will generate a valid pulse for new states.             
           case (state) is
                when st_startup =>
                  if RESET_N = '1' then
                      state <= st_init;
                  else
                      state <= st_startup;
                  end if;
                when st_init =>
                  if S_DATA.DVAL = '1' then
                                     state <= st_init_m0;
                                     M0_DATA <= ((others => '0'), (others => '0'), '1', '0');               
                  end if;
                when st_init_m0 =>
                              if M0_RESPONSE.DVAL = '1' then
                                     m0_size <= conv_integer(unsigned(M0_RESPONSE.DATA(15 downto 0)));       
                                     M1_DATA <= ((others => '0'), (others => '0'), '1', '0');   
                                     state <= st_init_m1;   
                                 else
                                     M0_DATA <= ((others => '0'), (others => '0'), '0', '0');               
                              end if;                            
                when st_init_m1 =>           
                              if M1_RESPONSE.DVAL = '1' then               
                                     m1_size <= conv_integer(unsigned(M1_RESPONSE.DATA(15 downto 0)));           
                                     S_RESPONSE <= (std_logic_vector(conv_unsigned(m0_size + conv_integer(unsigned(M1_RESPONSE.DATA(15 downto 0))), G_DATA_WIDTH)), '1');       
                                     state <= st_ready;   
                                 else
                                     M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                                               
                              end if;                             
                         when st_ready =>
                             S_RESPONSE <= ((others => '0'), '0');
                             M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                             M1_DATA <= ((others => '0'), (others => '0'), '0', '0');                            
                                if (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) < conv_unsigned(m0_size,G_ADDR_WIDTH))) then
                        M0_DATA <= S_DATA;           
                                       state <= st_request_m0;           
                                elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m0_size,G_ADDR_WIDTH)) and (unsigned(S_DATA.ADDR) < conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then
                        M1_DATA <= S_DATA;
                        M1_DATA.ADDR <= std_logic_vector(conv_unsigned(conv_integer(unsigned(S_DATA.ADDR)) - m0_size,G_ADDR_WIDTH));       
                                       state <= st_request_m1;                   
                                elsif (S_DATA.DVAL = '1' and (unsigned(S_DATA.ADDR) >= conv_unsigned(m1_size+m0_size,G_ADDR_WIDTH))) then               
                                       -- The received address is too big for this splitter. Something went wrong upstream in the DMM. Go into error state.
                                 S_RESPONSE <= (error_code, '1');
                                end if;
                         when st_request_m0 =>
                   if M0_RESPONSE.DVAL = '1' then
                       S_RESPONSE <= M0_RESPONSE;                    
                       state <= st_ready;           
                   else
                       M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                       state <= st_request_m0;
                   end if;
                when st_request_m1 =>
                   if M1_RESPONSE.DVAL = '1' then
                       S_RESPONSE <= M1_RESPONSE;                    
                       state <= st_ready;           
                   else
                       M0_DATA <= ((others => '0'), (others => '0'), '0', '0');
                       state <= st_request_m1;
                   end if;                              
                when others =>
                    state <= st_ready;
                end case;                         
         end if;       
      end if;
   end process;
    
end RTL;
 

0 Kudos
Historian
Historian
9,828 Views
Registered: ‎02-25-2008

Re: State machine synthesis problems

Jump to solution

jpnaude wrote:

Hi

 

Thanks for the responses. Interesting opinions that you gave, thanks. I'll need to get rid of those latches I agree.

 

Lately I've heard so many opinions on the best way to write a VHDL state machine and it seems like everyone has their own opinion (or at least where I work). Thus I decided to use the state machine templates found in the ISE Language Templates (which basically has a Moore and a Meally template) since synthesis tools (XST in our case) must surely find a specific way or writing a state machine as the optimal solution and thus produce the best synthesized result. One would think that the examples found in the ISE Language Templates will do exactly this, but after both of your posts it seems like that's not true.

 


Well, the two-process state machine can and does work. But the problem is that you must be very careful to make sure that your combinatorial process has an assignment to EACH signal in EVERY state, otherwise you get latches. This is somewhat maintainable with a small state machine (three or four states, three or four signals) but when you get into anything bigger, it's impossible to manage.

 

The one-process synchronous state machine solves those problems. Since every output is registered, by definition you won't get combinatorial latches. Also, if a state does not require that a signal be updated, you don't have to write an assigment to that signal in that state. This makes reading the code easier. The only thing that baffles newbies is that when you look at a simulation display, the state outputs "appear" to be one clock behind the state register. Example: say your state machine has a state called S_SETFOO and this state has a simple assignment: foo <= bar; When you simulate, your waveform display shows the state register indicating S_SETFOO and on the next clock tick, the signal foo takes on the value bar. This is the correct behavior (think about why this is the case) but it does cause lots of comp.arch.vhdl postings.

 

The textbooks love to talk about Mealy and Moore machines, but in the real world -- nobody cares. I couldn't tell you which is which.Don't try to force your design to fit one of those paradigms. Write  your code so that it's correct!

 

And yes, there is a serious disconnect between what the synthesis manual recommends and what's actually best. (WebCases have been opened and document-enhancement requests made, to no avail. Join the chorus!) I mean, seriously, the fscking Xilinx tools still by default includes the non-standard and deprecated std_logic_arith/std_logic_unsigned library use clauses in all VHDL sources that they generate (even if no math operations are occurring in the entity!).  The world has moved on to numeric_std, which works, is superior in all respects, and is a standard. Jeez, the templates still use the (clk'event and clk='1') construct instead of the rising_edge(clk) function that was added in VHDL'93 (sixteen years ago!)

 

Good luck,

-a

----------------------------Yes, I do this for a living.