LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;

ENTITY tb IS
END tb;

ARCHITECTURE test OF tb IS
    COMPONENT mt48lc4m32b2
        GENERIC (                                   -- Timing for -7 CL2
            tCK       : TIME    :=  7.500 ns;
            addr_bits : INTEGER := 12;
            data_bits : INTEGER := 32
        );
        PORT (
            Dq        : INOUT STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0) := (OTHERS => 'Z');
            Addr      : IN    STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0) := (OTHERS => '0');
            Ba        : IN    STD_LOGIC_VECTOR (1 DOWNTO 0) := "00";
            Clk       : IN    STD_LOGIC := '0';
            Cke       : IN    STD_LOGIC := '1';
            Cs_n      : IN    STD_LOGIC := '1';
            Cas_n     : IN    STD_LOGIC := '1';
            Ras_n     : IN    STD_LOGIC := '1';
            We_n      : IN    STD_LOGIC := '1';
            Dqm       : IN    STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000"
        ); 
    END COMPONENT;
  
    FOR ALL : mt48lc4m32b2 USE ENTITY work.mt48lc4m32b2 (behave);

    CONSTANT tCK       : TIME    :=  7.500 ns;
    CONSTANT addr_bits : INTEGER := 12;
    CONSTANT data_bits : INTEGER := 32;

    SIGNAL pDq       : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0);
    SIGNAL pAddr     : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
    SIGNAL pBa       : STD_LOGIC_VECTOR (1 DOWNTO 0);
    SIGNAL pClk      : STD_LOGIC;
    SIGNAL pCke      : STD_LOGIC;
    SIGNAL pCs_n     : STD_LOGIC;
    SIGNAL pCas_n    : STD_LOGIC;
    SIGNAL pRas_n    : STD_LOGIC;
    SIGNAL pWe_n     : STD_LOGIC;
    SIGNAL pDqm      : STD_LOGIC_VECTOR (3 DOWNTO 0);
    SIGNAL stim_done : boolean := false;
    SIGNAL clk_done : boolean := false;


BEGIN
    u1: mt48lc4m32b2
        PORT MAP(
            Dq        => pDq,
            Addr      => pAddr,
            Ba        => pBa,
            Clk       => pClk,
            Cke       => pCke,
            Cs_n      => pCs_n,
            Ras_n     => pRas_n,
            Cas_n     => pCas_n,
            We_n      => pWe_n,
            Dqm       => pDqm
        );

    stimulator : PROCESS
        PROCEDURE ACTIVE (Ba_in   : STD_LOGIC_VECTOR (1 DOWNTO 0);
                          Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
                          Dq_in   : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '0';
            pCas_n <= '1';
            pWe_n  <= '1';
            pDqm   <= "0000";
            pBa    <= Ba_in;
            pAddr  <= Addr_in;
            pDq    <= Dq_in;
            WAIT FOR tCK;
        END;

        PROCEDURE AUTO_REFRESH IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '0';
            pCas_n <= '0';
            pWe_n  <= '1';
            pDqm   <= "0000";
            --pBa    <= "00";
            --pAddr  <= (OTHERS => '0');
            pDq    <= (OTHERS => 'Z');
            WAIT FOR tCK;
        END;

        PROCEDURE BURST_TERM IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '1';
            pCas_n <= '1';
            pWe_n  <= '0';
            pDqm   <= "0000";
            --pBa    <= "00";
            --pAddr  <= (OTHERS => '0');
            pDq    <= (OTHERS => 'Z');
            WAIT FOR tCK;
        END;

        PROCEDURE LOAD_MODE_REG (Ba_in   : STD_LOGIC_VECTOR (1 DOWNTO 0);
                                 Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '0';
            pCas_n <= '0';
            pWe_n  <= '0';
            pDqm   <= "0000";
            pBa    <= Ba_in;
            pAddr  <= Addr_in;
            pDq    <= (OTHERS => 'Z');
            WAIT FOR tCK;
        END;

        PROCEDURE NOP (Dq_in : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '1';
            pCas_n <= '1';
            pWe_n  <= '1';
            pDqm   <= "0000";
            --pBa    <= "00";
            --pAddr  <= (OTHERS => '0');
            pDq    <= Dq_in;
            WAIT FOR tCK;
        END;

        PROCEDURE PRECHARGE (Ba_in   : STD_LOGIC_VECTOR (1 DOWNTO 0);
                             Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
                             Dq_in   : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '0';
            pCas_n <= '1';
            pWe_n  <= '0';
            pDqm   <= "0000";
            pBa    <= Ba_in;
            pAddr  <= Addr_in;
            pDq    <= Dq_in;
            WAIT FOR tCK;
        END;

        PROCEDURE READ (Ba_in   : STD_LOGIC_VECTOR (1 DOWNTO 0);
                        Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
                        Dq_in   : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '1';
            pCas_n <= '0';
            pWe_n  <= '1';
            pDqm   <= "0000";
            pBa    <= Ba_in;
            pAddr  <= Addr_in;
            pDq    <= Dq_in;
            WAIT FOR tCK;
        END;

        -- Write
        PROCEDURE WRITE (Ba_in   : STD_LOGIC_VECTOR (1 DOWNTO 0);
                         Addr_in : STD_LOGIC_VECTOR (addr_bits - 1 DOWNTO 0);
                         Dq_in   : STD_LOGIC_VECTOR (data_bits - 1 DOWNTO 0)) IS
        BEGIN
            pCke   <= '1';
            pCs_n  <= '0';
            pRas_n <= '1';
            pCas_n <= '0';
            pWe_n  <= '0';
            pDqm   <= "0000";
            pBa    <= Ba_in;
            pAddr  <= Addr_in;
            pDq    <= Dq_in;
            WAIT FOR tCK;
        END;
    BEGIN
    --  COMMAND          BA    ADDR            DQ
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
    --  We need 100 us power up sequence.  I use 10 NOPs here as a required example.
        PRECHARGE       ("00", "010000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        AUTO_REFRESH;
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        AUTO_REFRESH;
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        LOAD_MODE_REG   ("00", "000000100010");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        ACTIVE          ("00", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        ACTIVE          ("01", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        
        ACTIVE          ("10", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");

        ACTIVE          ("11", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");

        WRITE           ("00", "000000000000", "00000000000000000000000000000000");
        NOP             (                      "00000000000000000000000000000001");
        NOP             (                      "00000000000000000000000000000010");
        NOP             (                      "00000000000000000000000000000011");
        
        WRITE           ("01", "000000000000", "00000000000000000000000000000100");
        NOP             (                      "00000000000000000000000000000101");
        NOP             (                      "00000000000000000000000000000110");
        NOP             (                      "00000000000000000000000000000111");
        
        WRITE           ("10", "000000000000", "00000000000000000000000000001000");
        NOP             (                      "00000000000000000000000000001001");
        NOP             (                      "00000000000000000000000000001010");
        NOP             (                      "00000000000000000000000000001011");

        WRITE           ("11", "000000000000", "00000000000000000000000000001100");
        NOP             (                      "00000000000000000000000000001101");
        NOP             (                      "00000000000000000000000000001110");
        NOP             (                      "00000000000000000000000000001111");

        READ            ("00", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        READ            ("01", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        READ            ("10", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        READ            ("11", "000000000000", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
        NOP             (                      "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");

        ASSERT false
            REPORT "End of Stimulation File Detected!"
            SEVERITY note;
        stim_done <= true;
        WAIT;
    END PROCESS;

    clock : PROCESS
        VARIABLE done_time : time;
    BEGIN
        pclk <= '0';
        WAIT for tCK/2;
            WHILE not stim_done loop
                pclk <= '1';
                WAIT for tCK/2;
                pclk <= '0';
                WAIT for tCK/2;
            END LOOP;
            done_time := now + tCK;
            WHILE now < done_time LOOP  -- one last clock to finish last command
                pclk <= '1';
                WAIT for tCK/2;
                pclk <= '0';
                WAIT for tCK/2;
            END LOOP;
            ASSERT false 
                REPORT "Suspending clock activity"
                SEVERITY note;
            clk_done <= true;
            WAIT;
    END PROCESS;
END test;
