Search code examples
vhdl

simulating a VHDL FSM with ModelSim


Why the values of signals "state" and "return_state" don't switch in modelsim waveform. I'm simulating SD interface (SPI bus) with (ISE Design Suite 14.1) testbench and ModelSim SE plus 6.5. The problem is that the states names in the FSM don't switch in the waveform. Signals "state" and "return_state" are always in the "RST" state. I have declared signals "state", "return_state" and "type states" in the testbench. When I go trough the simulation with step function, the pointer shows that the simulation switches between the states. I need to see in the waveform when the states changes but I don't know what I did wrong. The code is on http://stevenmerrifield.com/tools/sd.vhd. Please help.

clk_period = 20 ns

initial part of the code:

begin

process(clk,reset)
    variable byte_counter : integer range 0 to WRITE_DATA_SIZE;
    variable bit_counter : integer range 0 to 160;
begin
    data_mode <= dm_in;

    if rising_edge(clk) then
        if (reset='1') then
            state <= RST;
            sclk_sig <= '0';
        else
            case state is

            when RST =>
                sclk_sig <= '0';
                cmd_out <= (others => '1');
                address <= x"00000000";
                byte_counter := 0;
                cmd_mode <= '1'; -- 0=data, 1=command
                response_mode <= '1';   -- 0=data, 1=command
                bit_counter := 160;
                cs <= '1';
                state <= INIT;

            when INIT =>        -- CS=1, send 80 clocks, CS=0
                if (bit_counter = 0) then
                    cs <= '0';
                    state <= CMD0;
                else
                    bit_counter := bit_counter - 1;
                    sclk_sig <= not sclk_sig;
                end if; 

            when CMD0 =>
                cmd_out <= x"FF400000000095";
                bit_counter := 55;
                return_state <= CMD55;
                state <= SEND_CMD;

If "reset" signal is set to '1' and then back to '0', the signals in "rst" state don't change except "cs" and "mosi" are set to '1'. "state" should get the value "INIT" and after 80 clocks the value "CMD0" but it keeps the value "rst". then:

-at 3310 ns "cs" gets the value '0'

The part of the code when should it happen:

when INIT =>        -- CS=1, send 80 clocks, CS=0
                if (bit_counter = 0) then
                    cs <= '0';
                    state <= CMD0;

Seems that the "state" has or should had the value "INIT" but in the waveform it still has the value "rst".

Testbench:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY simulacija IS
END simulacija;

ARCHITECTURE behavior OF simulacija IS 

COMPONENT sd_controller
PORT(
     cs : OUT  std_logic;
     mosi : OUT  std_logic;
     miso : IN  std_logic;
     sclk : OUT  std_logic;
     rd : IN  std_logic;
     wr : IN  std_logic;
     dm_in : IN  std_logic;
     reset : IN  std_logic;
     din : IN  std_logic_vector(7 downto 0);
     dout : OUT  std_logic_vector(7 downto 0);
     clk : IN  std_logic
    );
END COMPONENT;

signal miso : std_logic := '0';
signal rd : std_logic := '0';
signal wr : std_logic := '0';
signal dm_in : std_logic := '0';
signal reset : std_logic := '0';
signal din : std_logic_vector(7 downto 0) := (others => '0');
signal clk : std_logic := '0';


signal cs : std_logic := '0';
signal mosi : std_logic;
signal sclk : std_logic;
signal dout : std_logic_vector(7 downto 0);

type states is (
RST,
INIT,
CMD0,                               
CMD55,                  
CMD41,              

 IDLE,                      
READ_BLOCK,
READ_BLOCK_WAIT,
READ_BLOCK_DATA,
READ_BLOCK_CRC,
SEND_CMD,
RECEIVE_BYTE_WAIT,
RECEIVE_BYTE,
WRITE_BLOCK_CMD,
WRITE_BLOCK_INIT,       
 WRITE_BLOCK_DATA,      
WRITE_BLOCK_BYTE,       
WRITE_BLOCK_WAIT        
);
signal state, return_state : states;         
signal sclk_sig : std_logic := '0';             
signal cmd_out : std_logic_vector(55 downto 0);         
signal recv_data : std_logic_vector(7 downto 0);
signal address : std_logic_vector(31 downto 0);
signal cmd_mode : std_logic := '0';             
signal data_mode : std_logic := '1';        
signal response_mode : std_logic := '0';    
signal data_sig : std_logic_vector(7 downto 0) := x"00";

 constant clk_period : time := 20 ns;

 BEGIN

 uut: sd_controller PORT MAP (
      cs => cs,
      mosi => mosi,
      miso => miso,
      sclk => sclk,
      rd => rd,
      wr => wr,
      dm_in => dm_in,
      reset => reset,
      din => din,
      dout => dout,
      clk => clk
    );

clk_process :process
begin
    clk <= '0';
    wait for clk_period/2;
    clk <= '1';
    wait for clk_period/2;
end process;


stim_proc: process
begin   

  reset <= '1';
    wait for 80 ns;
  reset <= '0';
    wait;   
end process;
END;

Solution

  • you're seeing the state defined in your testbench! actually I expect that this was not on purpose, as there is absolutely no need to define the states type in your testbench too! if you add the architecture signals to your waveform, you'll see the states change!