library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

Library xpm;
use xpm.vcomponents.all;

-- NOTE: This entity instantiates Block RAM.
-- NOTE: Simutanous reads and writes to the same addresses have to be prevented by external means!

entity dual_port_ram is
        generic (
            ADDR_WIDTH      : integer := 4;
            DATA_WIDTH      : integer := 16
        );
        port (
            wr_clk      : in std_logic;
            rd_clk      : in std_logic;
            rd_addr     : in std_logic_vector(ADDR_WIDTH-1 downto 0);
            wr_addr     : in std_logic_vector(ADDR_WIDTH-1 downto 0);
            wen         : in std_logic;
            ren         : in std_logic;
            wr_data     : in std_logic_vector(DATA_WIDTH-1 downto 0);
            rd_data     : out std_logic_vector(DATA_WIDTH-1 downto 0)
        );
end entity;

architecture arch of dual_port_ram is
    
begin

    xpm_memory_sdpram_inst : xpm_memory_sdpram
        generic map (
            ADDR_WIDTH_A            => ADDR_WIDTH,
            ADDR_WIDTH_B            => ADDR_WIDTH,
            AUTO_SLEEP_TIME         => 0,
            BYTE_WRITE_WIDTH_A      => DATA_WIDTH,
            CLOCKING_MODE           => "independent_clock",
            ECC_MODE                => "no_ecc",
            MEMORY_INIT_FILE        => "none",
            MEMORY_INIT_PARAM       => "0",
            MEMORY_OPTIMIZATION     => "true",
            MEMORY_PRIMITIVE        => "block",
            MEMORY_SIZE             => DATA_WIDTH*(2**ADDR_WIDTH),
            MESSAGE_CONTROL         => 0,
            READ_DATA_WIDTH_B       => DATA_WIDTH,
            READ_LATENCY_B          => 1,
            READ_RESET_VALUE_B      => "0",
            RST_MODE_A              => "SYNC",
            RST_MODE_B              => "SYNC",
            USE_EMBEDDED_CONSTRAINT => 0, --TODO
            USE_MEM_INIT            => 1,
            WAKEUP_TIME             => "disable_sleep",
            WRITE_DATA_WIDTH_A      => DATA_WIDTH,
            WRITE_MODE_B            => "no_change"
        )
        port map (
            dbiterrb        => open,
            doutb           => rd_data,
            sbiterrb        => open,
            addra           => wr_addr,
            addrb           => rd_addr,
            clka            => wr_clk,
            clkb            => rd_clk,
            dina            => wr_data,
            ena             => wen,
            enb             => ren,
            injectdbiterra  => '0',
            injectsbiterra  => '0',
            regceb          => '1',
            rstb            => '0',
            sleep           => '0',
            wea             => (others => wen) --1-bit Vector
        );

end architecture;