2
\$\begingroup\$

I wrote an ASRAM in VHDL and simulate it. I get many "X" if I try to read. I know that this problem is caused by too many drivers on one net but I didn't find the problem nor solved it.

Appreciate some help.

[SIMULATION] 1]

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;
use work.mem_type.all;


entity async_sram_tristate_new_nBit_test is    
    generic (   DAT_WIDTH:  natural := 16;  -- number of data bits 
                ADDR_WIDTH: natural := 6); -- number of address bits

    port (      ram_dat : inout std_logic_vector ((DAT_WIDTH - 1) downto 0); -- bidirectional data bus to/from the SRAM device
                ram_addr: in    std_logic_vector ((ADDR_WIDTH - 1) downto 0);  -- address bus of the SRAM device                
                nCS     : in    std_logic;   -- low-active Chip-Enable of the SRAM device; defaults to '1' (inactive)
                nOE     : in    std_logic;   -- low-active Output-Enable of the SRAM device; defaults to '1' (inactive)
                nWE     : in    std_logic;   -- low-active Write-Enable of the SRAM device; defaults to '1' (inactive)               
                clk     : in    std_logic;

                data_fpga_read   : out  ram_array_16(0 to (2**(ADDR_WIDTH-1) - 1)); 
                data_fpga_write  : in ram_array_16(0 to (2**(ADDR_WIDTH-1) - 1))

            );
               -- ram_wait : out std_logic := '0'); -- wait pin to stretch the strobe period; defaults to '0' (inactive)  
end async_sram_tristate_new_nBit_test;

architecture Behavioral of async_sram_tristate_new_nBit_test is

constant ADRR_HALF  : natural := 2**(ADDR_WIDTH-1); 
constant MEM_SIZE   : natural := 2**(ADDR_WIDTH); 
constant DEPTH      : natural := 1;

signal ram : ram_array_16(0 to 2**(ADDR_WIDTH) - 1);              -- declerates a variable ram of type ram_array // this is the REAL memory
signal ram_output_buffer : std_logic_vector ((DAT_WIDTH - 1) downto 0); -- declerates a variable ram of type ram_array to buffer the output 
signal addr_buffer : std_logic_vector((ADDR_WIDTH - 1) downto 0); 
signal nWE_buffer, nOE_buffer : std_logic_vector(DEPTH downto 0);
begin
    -------------------------------------------------------------------------
    -- TRISTATE BUFFER 
    -------------------------------------------------------------------------

    ram_dat <= ram_output_buffer when nOE_buffer(DEPTH) = '0' else (others => 'Z'); -- tristate buffer 

    -------------------------------------------------------------------------
    -- ADRESS READ AND BUFFER
    -------------------------------------------------------------------------
    read_addr: process(clk)
    begin   
        if(rising_edge(clk)) then
            addr_buffer <= ram_addr;            
        end if;
    end process;

    -------------------------------------------------------------------------
    -- READ PROCESS
    -------------------------------------------------------------------------
    read_ram : process (clk)
    begin
        if(rising_edge(clk)) then
        nOE_buffer <= nOE_buffer(DEPTH - 1 downto 0) & nOE;
            if (nOE_buffer(DEPTH) = '0') then
                if (addr_buffer(ADDR_WIDTH - 1) = '0') then -- checks if the adress is in the "read-only" space   
                    ram_output_buffer <= ram(conv_integer(unsigned(addr_buffer))); -- makes the data aviable via the output buffer 
                end if;                   
            end if;
        end if;
    end process;

    -------------------------------------------------------------------------
    -- WRITE PROCESS
    -------------------------------------------------------------------------
    write_ram : process(clk)
    begin    
        if(rising_edge(clk)) then
        nWE_buffer <= nWE_buffer(DEPTH - 1 downto 0) & nWE;
            -- nWE = 0 indicates that the microcontroller wants to write data 
            if (nWE_buffer(DEPTH) = '0') then
                if (addr_buffer(ADDR_WIDTH -1) = '0') then
                    ram(conv_integer(unsigned(addr_buffer))) <= ram_dat;    
                end if;
            end if;
        end if;
    end process;


    --ram(2**(ADDR_WIDTH-1) to (2**ADDR_WIDTH)-1) <= data_fpga_write;
    --data_fpga_read <= ram(0 to (2**(ADDR_WIDTH-1)- 1));

end Behavioral;
\$\endgroup\$
4
  • 2
    \$\begingroup\$ I would bet it is because ram_dat is inout. \$\endgroup\$
    – DKNguyen
    Commented Dec 5, 2019 at 16:02
  • 3
    \$\begingroup\$ Your testbench should be the culprit. 'inout' have to be dealt carefully. Much better to use separate data channels for read and write. \$\endgroup\$
    – Mitu Raj
    Commented Dec 5, 2019 at 16:04
  • \$\begingroup\$ What data was previously written to the address that reads xxxxx? \$\endgroup\$ Commented Dec 5, 2019 at 18:31
  • 2
    \$\begingroup\$ The above comments seem like the best bet (we would need to see your testbench code to be sure). In both the code and the testbench, drive the signal to 'Z' when you want to stop driving the line. Two things driving an inout with different values will give X's. \$\endgroup\$ Commented Dec 5, 2019 at 22:42

1 Answer 1

1
\$\begingroup\$

As multiple commenters suggested, because ram_dat is inout, it can (but must not) be driven at the same time by your module and the system instantiating your module.

Make sure you understand how your protocol guarantees absence of multiple drivers (by switching to Z when not in the "driving seat"), and verify that both "outside" and "inside" of the module adhere to this protocol (it may be both are in the wrong!).

I am just summarizing comments into an answer so it's easier to find later.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.