diff --git a/src/dp_mem_ctrl.vhd b/src/dp_mem_ctrl.vhd new file mode 100644 index 0000000..0f346d9 --- /dev/null +++ b/src/dp_mem_ctrl.vhd @@ -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;