Add Dual Port Memory Controller

This commit is contained in:
Greek 2021-12-08 11:27:59 +01:00
parent 46ca2228b6
commit 622ebf6083

123
src/dp_mem_ctrl.vhd Normal file
View File

@ -0,0 +1,123 @@
-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity dp_mem_ctrl is
generic (
ADDR_WIDTH : natural;
DATA_WIDTH : natural;
MEMORY_DEPTH : natural;
MAX_BURST_LENGTH : natural
);
port (
-- SYSTEM
clk : in std_logic;
reset : in std_logic;
-- READ PORT
raddr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
rvalid_in : in std_logic;
rready_in : out std_logic;
rvalid_out : out std_logic;
rready_out : in std_logic;
rdata_out : out std_logic_vector(DATA_WIDTH-1 downto 0);
-- WRITE PORT
waddr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
wvalid_in : in std_logic;
wready_in : out std_logic;
wdata_in : in std_logic_vector(DATA_WIDTH-1 downto 0)
);
end entity;
architecture arch of dp_mem_ctrl is
-- *CONSTANT DECLARATION*
constant READ_LATENCY : natural := 1;
-- *TYPE DECLARATION*
-- *SIGNAL DECLARATION*
signal mem_read_data : std_logic_vector(DATA_WIDTH-1 downto 0);
signal delay_line : std_logic_vector(READ_LATENCY-1 downto 0);
signal fifo_empty : std_logic;
signal fifo_cnt : natural range 0 to MAX_BURST_LENGTH;
signal delay_cnt : natural range 0 to READ_LATENCY;
signal rready_in_sig, wready_in_sig, rvalid_out_sig : std_logic;
begin
--*****COMPONENT INSTANTIATION*****
ram_inst : configuration work.dual_port_ram_cfg
generic map (
ADDR_WIDTH => ADDR_WIDTH,
DATA_WIDTH => DATA_WIDTH,
MEMORY_DEPTH => MEMORY_DEPTH
)
port map (
clk => clk,
raddr => raddr,
waddr => waddr,
wen => wready_in_sig and wvalid_in,
ren => rready_in_sig and rvalid_in,
wr_data => wdata_in,
rd_data => mem_read_data
);
wready_in_sig <= '1'; -- We are always ready to receive writes
wready_in <= wready_in_sig;
rready_in_sig <= '0' when (fifo_cnt - delay_cnt = 0) else '1';
rready_in <= rready_in_sig;
rvalid_out_sig <= not fifo_empty;
rvalid_out <= rvalid_out_sig;
delay_line_prc : process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
delay_line <= (others => '0');
delay_cnt <= 0;
else
-- Shift Right
if (READ_LATENCY > 1) then
delay_line(READ_LATENCY-2 downto 0) <= delay_line(READ_LATENCY-1 downto 1);
delay_line(READ_LATENCY-1) <= rready_in_sig and rvalid_in;
if ((rready_in_sig and rvalid_in) = '1' and delay_line(1) = '0') then
delay_cnt <= delay_cnt + 1;
elsif ((rready_in_sig and rvalid_in) = '0' and delay_line(1) = '1') then
delay_cnt <= delay_cnt - 1;
end if;
else -- READ_LATENCY = 1
delay_line(0) <= rready_in_sig and rvalid_in;
if ((rready_in_sig and rvalid_in) = '1' and delay_line(0) = '0') then
delay_cnt <= delay_cnt + 1;
elsif ((rready_in_sig and rvalid_in) = '0' and delay_line(0) = '1') then
delay_cnt <= delay_cnt - 1;
end if;
end if;
end if;
end if;
end process;
burst_fifo_inst : configuration work.FWFT_FIFO_cfg
generic map (
FIFO_DEPTH => MAX_BURST_LENGTH,
DATA_WIDTH => DATA_WIDTH
)
port map (
clk => clk,
reset => reset,
data_in => mem_read_data,
write => delay_line(0),
read => rready_out and rvalid_out_sig,
data_out => rdata_out,
empty => fifo_empty,
full => open,
free => fifo_cnt
);
end architecture;