the read process will be combinational, so both ports could read a flop in same time.
If you allow both port to write at same time, you need to specify some priority or ignore both write request.
ENTITY DPRAM_trial
PORT
nreset : IN STD_LOGIC; -- asynchronous low active reset
clk : IN STD_LOGIC; -- system clock
-- first port
port_1_cs : IN STD_LOGIC; -- port 1 chip select
port_1_wr : IN STD_LOGIC; -- port 1 write condition
port_1_rd : IN STD_LOCIG; -- port 1 read condition
port_1_address : IN STD_LOGIC; -- port 1 address
port_1_data_wr : IN STD_LOGIC; -- port 1 data write
port_1_data_rd : OUT STD_LOGIC; -- port 1 data read
-- second port
port_2_cs : IN STD_LOGIC; -- port 2 chip select
port_2_wr : IN STD_LOGIC; -- port 2 write condition
port_2_rd : IN STD_LOCIG; -- port 2 read condition
port_2_address : IN STD_LOGIC; -- port 2 address
port_2_data_wr : IN STD_LOGIC; -- port 2 data write
port_2_data_rd : OUT STD_LOGIC; -- port 2 data read
);
ARCHITECTURE example IS
BEGIN
p_sync: process(nreset, clk)
BEGIN
IF nreset='0' THEN
mem <= '0';
elsif clk'event AND clk='1' THEN
-- port_1 has predominant versus port_2
IF port_1_cs='1' AND port_1_address='1' AND port_1_wr='1' THEN
mem <= port_1_data_wr;
ELSIF port_2_cs='1' AND port_2_address='1' AND port_2_wr='1' THEN
mem <= port_2_data_wr;
END IF;
END IF;
END PROCESS p_sync;
p_async
ROCESS (port_1_cs, port_1_rd, port_1_address, port_2_cs, port_2_rd, port_2_address)
BEGIN
-- first port
port_1_data_rd <= '0'; -- default value
IF port_1_cs='1' AND port_1_rd='1' THEN
IF port_1_address='1' THEN port_1_data_wr <= mem; END IF;
END IF;
-- second port
port_2_data_rd <= '0'; --default value
IF port_2_cs='1' AND port_2_rd='1' THEN
IF port_2_address='1' THEN port_2_data_wr <= mem; END IF;
END IF;
END PROCESS p_async;
END try;
in this quick example, the first port has the priority over the port 2, in the writing condition.
after you could used a case versus IF for the address section.
if I will wrote the code, I will used "vectorisation", to use FOR GENERATE for the read process, because there is two times the same process.
This code only replace the memory element, the fifo logic could be outside, to easily swap between a real memory or a flop instantiation.
The nreset signal could not be mandatory, depending of your guide line, or the area trade off (look at your std cell, and you will see some "big reduction of area/power" by using flop without reset versus real memory)
Is it what you look for?