PCS-2/comp/block_memory.vhd

102 lines
3.8 KiB
VHDL

-- block_memory.vhd: General storage memory build from BlockRAMs or M20Ks with one read and one write port
-- Copyright (C) 2019 FIT BUT
-- Author(s): Lukas Kekely <ikekely@fit.vutbr.cz>
--
-- SPDX-License-Identifier: BSD-3-Clause
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
use work.functions_package.clog2;
entity block_memory is
generic(
-- Size of the memory.
-- ITEMS individual records addressed from 0 to ITEMS-1, each ITEM_WIDTH bits wide.
ITEM_WIDTH : natural := 32;
ITEMS : natural := 1024;
-- Enables output data register on read port for better frequency.
-- Latency of reading data from the memory is 1 clock cycle when false, and 2 clock cycles when true.
OUTPUT_REGISTER : boolean := true
);
port (
-- Main clock signal and its synchronous reset.
CLK : in std_logic;
RESET : in std_logic;
-- Read interface ----------------------------------------------------------
READ_ADDRESS : in std_logic_vector(clog2(ITEMS)-1 downto 0); -- item address to read
READ_VALID : in std_logic; -- read is valid
READ_DATA : out std_logic_vector(ITEM_WIDTH-1 downto 0); -- read data (note: read latency!)
READ_DATA_VALID : out std_logic; -- delayed read valid flag
-- Write interface ---------------------------------------------------------
WRITE_DATA : in std_logic_vector(ITEM_WIDTH-1 downto 0); -- data to write
WRITE_ADDRESS : in std_logic_vector(clog2(ITEMS)-1 downto 0); -- item address to write
WRITE_VALID : in std_logic -- perform write operation
);
end entity;
architecture behavioral of block_memory is
type memory_type is array(0 to ITEMS-1) of std_logic_vector(ITEM_WIDTH-1 downto 0);
signal memory : memory_type;
signal memory_data : std_logic_vector(ITEM_WIDTH-1 downto 0);
signal memory_data_valid : std_logic;
attribute ramstyle : string;
attribute ramstyle of memory : signal is "M20K";
begin
-- Unsupported configurations checks -----------------------------------------
assert ITEMS > 1 report "FAILURE: Block Memory must have at least two items!" severity failure;
assert ITEM_WIDTH > 0 report "FAILURE: Block Memory item must be at least 1 bit wide!" severity failure;
-- Runtime error checks ------------------------------------------------------
assert conv_integer(READ_ADDRESS) < ITEMS or RESET/= '0' report "ERROR: Block Memory read out of bounds!" severity error;
assert conv_integer(WRITE_ADDRESS) < ITEMS or RESET/= '0' report "ERROR: Block Memory write out of bounds!" severity error;
-- Memory core implementation ------------------------------------------------
storage_core: process(CLK)
begin
if rising_edge(CLK) then
-- Write port
if WRITE_VALID = '1' then
memory(conv_integer(WRITE_ADDRESS)) <= WRITE_DATA;
end if;
-- Read port
memory_data <= memory(conv_integer(READ_ADDRESS));
if RESET = '1' then
memory_data_valid <= '0';
else
memory_data_valid <= READ_VALID;
end if;
end if;
end process;
-- Optional output register on read port -------------------------------------
registered_read: if OUTPUT_REGISTER generate
read_register: process(CLK)
begin
if rising_edge(CLK) then
READ_DATA <= memory_data;
if RESET = '1' then
READ_DATA_VALID <= '0';
else
READ_DATA_VALID <= memory_data_valid;
end if;
end if;
end process;
end generate;
direct_read: if not OUTPUT_REGISTER generate
READ_DATA <= memory_data;
READ_DATA_VALID <= memory_data_valid;
end generate;
end architecture;