Search code examples
vhdl

single port ram with timming specifications


generic(    -- read cycle
            constant taa : time := 120 ns;
                constant tacs: time := 120 ns;
                constant tclz: time := 10 ns;
                constant tchz :time := 10 ns;
                constant toh :time := 10 ns;
    -- write cycle begins           
                constant twc : time := 120 ns;
                constant taw:time := 105 ns;
                constant twp :time := 70 ns;
                constant twhz: time := 35 ns;
                constant tdw :time := 35 ns;
                constant tdh :time := 0 ns;
                constant tow :time := 10 ns);
type ramtype is array (0 downto 255) of std_logic_vector(7 downto 0);
signal ram: ramtype :=( others =>(others =>'0'));    

if(rising_edge(we) and cs'delayed = '0') or
            (falling_edge(cs) and we'delayed = '0') then 
                ram(conv_integer(address'delayed)) <= to_stdlogicvector(data'delayed); -- error here
                data <= transport data'delayed after tow;
            end if;
            if(falling_edge(we) and cs = '0') then 
                data <= transport "ZZZZZZZZ" after twhz;
            end if;

        if (cs'event ='1' and oe = '0') then  -- error here
                if cs = '1' then
                    data <= transport "ZZZZZZZZ" after tchz;
                elsif we = '1' then
                    data <= "XXXXXXXX" after tchz;
                    data <= transport to_stdlogicvector(ram(conv_integer(address))) after tacs; --error here
                end if;
            end if;

            if address'event and cs = '0' and oe = '0' and we = '1' then 
                    data <= "XXXXXXXX" after toh;
                    data <= transport to_stdlogicvector(ram(conv_integer(address))) after taa; -- error here
            end if;

        end process;
    end Behavioral;

getting errors in the following lines saying that Line 77: Expecting type natural for . Line 77: Indexed name is not a std_logic_vector Line 72: found '0' definitions of operator "=", cannot determine exact overloaded matching definition for "=" Line 83: Formal has no actual or default value. Line 83: Expecting type natural for . ine 83: Indexed name is not a std_logic_vector

unable to figure out what might be the exact error


Solution

  • Okay. I filled in the blanks it got it to analyze:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity single_port_ram is
        generic (    
            -- read cycle
            constant taa:   time := 120 ns;
            constant tacs:  time := 120 ns;
            constant tclz:  time := 10 ns;
            constant tchz:  time := 10 ns;
            constant toh:   time := 10 ns;
            -- write cycle begins           
            constant twc:   time := 120 ns;
            constant taw:   time := 105 ns;
            constant twp:   time := 70 ns;
            constant twhz:  time := 35 ns;
            constant tdw:   time := 35 ns;
            constant tdh:   time := 0 ns;
            constant tow:   time := 10 ns
        );
        port (
            address:    in      std_logic_vector(7 downto 0);
            data:       inout   std_logic_vector(7 downto 0);
            we:         in      std_logic;
            cs:         in      std_logic;
            oe:         in      std_logic
        );
    end entity;
    
    architecture behavioral of single_port_ram is
    
    type ramtype is array (0 downto 255) of std_logic_vector(7 downto 0);
    signal ram: ramtype :=( others =>(others =>'0')); 
    
    begin
    
    
    SINGLE_PROCESS:
        process(we, cs, address, data, oe)
        begin
            if ( rising_edge(we) and cs'delayed = '0') or
               (falling_edge(cs) and we'delayed = '0') then 
                ram(to_integer(unsigned (address'delayed))) <=  data'delayed;
                -- to_stdlogicvector(data'delayed); -- error here
                data <= transport data'delayed after tow;
            end if;
    
            if(falling_edge(we) and cs = '0') then 
                data <= transport "ZZZZZZZZ" after twhz;
            end if;
    
            if (cs'event  and oe = '0') then  -- error here -- cs'event = '1'
                if cs = '1' then
                    data <= transport "ZZZZZZZZ" after tchz;
                 elsif we = '1' then
                    data <= "XXXXXXXX" after tchz;
                    data <= transport std_logic_vector(ram(to_integer(unsigned(address)))) after tacs; --error here
                end if;
            end if;
    
             if address'event and cs = '0' and oe = '0' and we = '1' then 
                    data <= "XXXXXXXX" after toh;
                    data <= transport std_logic_vector(ram(to_integer(unsigned(address)))) after taa; -- error here
            end if;
    
        end process;
    end behavioral;
    

    I'm not vouching for it's functionality without a test bench.

    From the unsigned type conversions you could gather this is done on a pre VHDL-2008 package numeric_std tool (ghdl). In -2008 std_logic_vector and unsigned are both resolved subtypes of std_ulogic_vector. The unsigned type conversion wouldn't be necessary.

    You seem to have been using a Mentor Graphics version of the IEEE library, package std_logic_arith if I'm not mistaken.

    Note that 'EVENT returns a boolean, and an equality test against '1' doesn't analyze. You're error marker comments are still present.

    Package numeric_std provides to_integer instead of conv_integer.

    And the original looked better, albeit implemented in type BIT where possible.

    (This was originally taken from Charles H. Roth, Jr.'s 1998 book Digital System Design Using VHDL, Chapter 9 . I went looking when I noticed the language of your question avoided claiming authorship).

    -- memory model with timing (OE_b=0) 
    library ieee;
    use ieee.std_logic_1164.all;
    library bitlib;
    use bitlib.bit_pack.all;
    
    entity static_RAM is
        generic (
            constant tAA:   time := 120 ns; -- 6116 static CMOS RAM 
            constant tACS:  time := 120 ns; 
            constant tCLZ:  time := 10 ns; 
            constant tCHZ:  time := 10 ns; 
            constant tOH:   time := 10 ns; 
            constant tWC:   time := 120 ns; 
            constant tAW:   time := 105 ns; 
            constant tWP:   time := 70 ns; 
            constant tWHZ:  time := 35 ns; 
            constant tDW:   time := 35 ns; 
            constant tDH:   time := 0 ns;
            constant tOW:   time := 10 ns
        );
        port (
            CS_b, WE_b, OE_b:   in      bit;
            Address:            in      bit_vector(7 downto 0);
            Data:               inout   std_logic_vector(7 downto 0) := 
                                            (others => 'Z')
        ); 
    end Static_RAM;
    
    architecture SRAM of Static_RAM is
    
        type RAMtype is array(0 to 255) of bit_vector(7 downto 0); 
        signal RAM1: RAMtype := (others => (others => '0')); 
    begin
    
    RAM: 
        process 
        begin
            if (rising_edge(WE_b) and CS_b'delayed = '0') or 
               (rising_edge(CS_b) and WE_b'delayed = '0') then
                RAM1(vec2int(Address'delayed)) <= to_bitvector(Data'delayed);           --write 
                if CS_b = '0' then
                    Data <= transport Data'delayed after tOW; 
                end if;
            end if;
            if falling_edge(WE_b) and CS_b = '0' then
                Data <= transport "ZZZZZZZZ" after tWHZ; 
            end if;
        --read back after write
            if CS_b'event and OE_b = '0' then
                if CS_b = '1' then 
                    Data <= transport "ZZZZZZZZ" after tCHZ; 
                elsif WE_b = '1' then --read
                    Data <= "XXXXXXXX" after tCLZ;
        -- RAM is deselected
                    Data <= transport to_stdlogicvector(RAM1(vec2int(Address))) after tACS; 
                end if;
            end if;
            wait on CS_b, WE_b, Address;
        end process RAM;
    check: 
        process 
        begin
        if CS_b'delayed = '0' and NOW /= 0 ns then 
            if address'event then
                assert (address'delayed'stable(tWC)) 
                -- tRC = tWC assumed report "Address cycle time too short"
                severity WARNING;
            end if;
            if rising_edge(WE_b) then
                assert (address'delayed'stable(tAW))
                report "Address not valid long enough to end of write"
                severity WARNING;
                assert (WE_b'delayed'stable(tWP))
                report "Write pulse too short"
                severity WARNING;
                assert (Data'delayed'stable(tDW))
                report "Data setup time too short"
                severity WARNING;
                wait for tDH;
                assert (Data'last_event >= tDH)
                report "Data hold time too short" 
                severity WARNING;
            end if;
        end if;
            wait on WE_b, address, CS_b;
        end process check;
    end SRAM;
    

    And the original converted cleanly:

    -- memory model with timing (OE_b=0) 
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    -- library bitlib;
    -- use bitlib.bit_pack.all;
    
    entity static_RAM is
        generic (
            constant tAA:   time := 120 ns; -- 6116 static CMOS RAM 
            constant tACS:  time := 120 ns; 
            constant tCLZ:  time := 10 ns; 
            constant tCHZ:  time := 10 ns; 
            constant tOH:   time := 10 ns; 
            constant tWC:   time := 120 ns; 
            constant tAW:   time := 105 ns; 
            constant tWP:   time := 70 ns; 
            constant tWHZ:  time := 35 ns; 
            constant tDW:   time := 35 ns; 
            constant tDH:   time := 0 ns;
            constant tOW:   time := 10 ns
        );
        port (
            CS_b, WE_b, OE_b:   in      std_logic;
            Address:            in      std_logic_vector(7 downto 0);
            Data:               inout   std_logic_vector(7 downto 0) := 
                                            (others => 'Z')
        ); 
    end Static_RAM;
    
    architecture SRAM of Static_RAM is
    
        type RAMtype is array(0 to 255) of std_logic_vector(7 downto 0); 
        signal RAM1: RAMtype := (others => (others => '0')); 
    begin
    
    RAM: 
        process 
        begin
            if (rising_edge(WE_b) and CS_b'delayed = '0') or 
               (rising_edge(CS_b) and WE_b'delayed = '0') then
                RAM1(to_integer(unsigned(Address'delayed))) 
                    <= Data'delayed;           --write 
                if CS_b = '0' then
                    Data <= transport Data'delayed after tOW; 
                end if;
            end if;
            if falling_edge(WE_b) and CS_b = '0' then
                Data <= transport "ZZZZZZZZ" after tWHZ; 
            end if;
        --read back after write
            if CS_b'event and OE_b = '0' then
                if CS_b = '1' then 
                    Data <= transport "ZZZZZZZZ" after tCHZ; 
                elsif WE_b = '1' then --read
                    Data <= "XXXXXXXX" after tCLZ;
        -- RAM is deselected
                    Data <= transport RAM1(to_integer(unsigned(Address))) after tACS; 
                end if;
            end if;
            wait on CS_b, WE_b, Address;
        end process RAM;
    check: 
        process 
        begin
        if CS_b'delayed = '0' and NOW /= 0 ns then 
            if address'event then
                assert (address'delayed'stable(tWC)) 
                -- tRC = tWC assumed report "Address cycle time too short"
                severity WARNING;
            end if;
            if rising_edge(WE_b) then
                assert (address'delayed'stable(tAW))
                report "Address not valid long enough to end of write"
                severity WARNING;
                assert (WE_b'delayed'stable(tWP))
                report "Write pulse too short"
                severity WARNING;
                assert (Data'delayed'stable(tDW))
                report "Data setup time too short"
                severity WARNING;
                wait for tDH;
                assert (Data'last_event >= tDH)
                report "Data hold time too short" 
                severity WARNING;
            end if;
        end if;
            wait on WE_b, address, CS_b;
        end process check;
    end SRAM;
    

    And analyzes.

    addendum

    The questioner commented on the use of BITLIB, so I went looking.

    The book author has a resource page (Digital Systems Design Using VHDL) and the VHDL source code found in the be found here indexed by chapter and figure numbers from the book. The BITLIB library VHDL code is found in Bit_pack.vhd,

    A little looking around last night also reveals there's a second edition of the book published in 2008.