-------------------------------------------------------------------------------- -- CERN BE-CO-HT -- General Cores Library -- https://www.ohwr.org/projects/general-cores -------------------------------------------------------------------------------- -- -- unit name: generic_dpram -- -- description: True dual-port synchronous RAM for Xilinx FPGAs with: -- - configurable address and data bus width -- - byte-addressing mode (data bus width restricted to multiple of 8 bits) -- -- todo: -- - loading initial contents from file -- - add support for read-first/write-first address conflict resulution (only -- supported by Xilinx in VHDL templates) -- -------------------------------------------------------------------------------- -- Copyright CERN 2011-2018 -------------------------------------------------------------------------------- -- Copyright and related rights are licensed under the Solderpad Hardware -- License, Version 2.0 (the "License"); you may not use this file except -- in compliance with the License. You may obtain a copy of the License at -- http://solderpad.org/licenses/SHL-2.0. -- Unless required by applicable law or agreed to in writing, software, -- hardware and materials distributed under this License is distributed on an -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express -- or implied. See the License for the specific language governing permissions -- and limitations under the License. -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; library work; use work.genram_pkg.all; use work.memory_loader_pkg.all; entity generic_dpram is generic ( -- standard parameters g_data_width : natural := 32; g_size : natural := 16384; g_with_byte_enable : boolean := false; g_addr_conflict_resolution : string := "read_first"; g_init_file : string := ""; g_dual_clock : boolean := true; g_fail_if_file_not_found : boolean := true ); port ( rst_n_i : in std_logic := '1'; -- synchronous reset, active LO -- Port A clka_i : in std_logic; bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); wea_i : in std_logic; aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); da_i : in std_logic_vector(g_data_width-1 downto 0); qa_o : out std_logic_vector(g_data_width-1 downto 0); -- Port B clkb_i : in std_logic; bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); web_i : in std_logic; ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); db_i : in std_logic_vector(g_data_width-1 downto 0); qb_o : out std_logic_vector(g_data_width-1 downto 0) ); end generic_dpram; architecture syn of generic_dpram is constant c_gen_split :boolean := (g_dual_clock = false and g_data_width=32 and g_with_byte_enable=true and (g_addr_conflict_resolution="dont_care" or g_addr_conflict_resolution="read_first")); constant c_gen_sc :boolean := (not c_gen_split) and (not g_dual_clock); constant c_gen_dc :boolean := g_dual_clock; component generic_dpram_split generic ( g_size : natural; g_addr_conflict_resolution : string := "dont_care"; g_init_file : string := "none"; g_fail_if_file_not_found : boolean := true); port ( rst_n_i : in std_logic := '1'; clk_i : in std_logic; bwea_i : in std_logic_vector(3 downto 0); wea_i : in std_logic; aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); da_i : in std_logic_vector(31 downto 0); qa_o : out std_logic_vector(31 downto 0); bweb_i : in std_logic_vector(3 downto 0); web_i : in std_logic; ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); db_i : in std_logic_vector(31 downto 0); qb_o : out std_logic_vector(31 downto 0)); end component; component generic_dpram_sameclock generic ( g_data_width : natural; g_size : natural; g_with_byte_enable : boolean; g_addr_conflict_resolution : string; g_init_file : string; g_fail_if_file_not_found : boolean); port ( rst_n_i : in std_logic := '1'; clk_i : in std_logic; bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); wea_i : in std_logic; aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); da_i : in std_logic_vector(g_data_width-1 downto 0); qa_o : out std_logic_vector(g_data_width-1 downto 0); bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); web_i : in std_logic; ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); db_i : in std_logic_vector(g_data_width-1 downto 0); qb_o : out std_logic_vector(g_data_width-1 downto 0)); end component; component generic_dpram_dualclock generic ( g_data_width : natural; g_size : natural; g_with_byte_enable : boolean; g_addr_conflict_resolution : string; g_init_file : string; g_fail_if_file_not_found : boolean); port ( rst_n_i : in std_logic := '1'; clka_i : in std_logic; bwea_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); wea_i : in std_logic; aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); da_i : in std_logic_vector(g_data_width-1 downto 0); qa_o : out std_logic_vector(g_data_width-1 downto 0); clkb_i : in std_logic; bweb_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); web_i : in std_logic; ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); db_i : in std_logic_vector(g_data_width-1 downto 0); qb_o : out std_logic_vector(g_data_width-1 downto 0)); end component; begin -- generic_dpram_split is like generic_dpram_sameclock, but hardcoded to -- 32-bit data width and split into 4 BRAMs, each of them 8-bit wide. It's -- better for Xilinx ISE, because it's unable to infer DPRAM with byte-write -- enables without using huge number of LUTs. -- Since it's hardcoded to 32-bits data width, we need to keep -- generic_dpram_sameclock as well. For reasons why generic_dpram_split is -- hardcoded to 32-bits please check the Note in generic_dpram_split.vhd. gen_splitram: if c_gen_split generate U_RAM_SPLIT: generic_dpram_split generic map( g_size => g_size, g_addr_conflict_resolution => g_addr_conflict_resolution, g_init_file => g_init_file, g_fail_if_file_not_found => g_fail_if_file_not_found) port map( rst_n_i => rst_n_i, clk_i => clka_i, bwea_i => bwea_i, wea_i => wea_i, aa_i => aa_i, da_i => da_i, qa_o => qa_o, bweb_i => bweb_i, web_i => web_i, ab_i => ab_i, db_i => db_i, qb_o => qb_o); end generate gen_splitram; gen_single_clk : if c_gen_sc generate U_RAM_SC: generic_dpram_sameclock generic map ( g_data_width => g_data_width, g_size => g_size, g_with_byte_enable => g_with_byte_enable, g_addr_conflict_resolution => g_addr_conflict_resolution, g_init_file => g_init_file, g_fail_if_file_not_found => g_fail_if_file_not_found) port map ( rst_n_i => rst_n_i, clk_i => clka_i, bwea_i => bwea_i, wea_i => wea_i, aa_i => aa_i, da_i => da_i, qa_o => qa_o, bweb_i => bweb_i, web_i => web_i, ab_i => ab_i, db_i => db_i, qb_o => qb_o); end generate gen_single_clk; gen_dual_clk : if c_gen_dc generate U_RAM_DC: generic_dpram_dualclock generic map ( g_data_width => g_data_width, g_size => g_size, g_with_byte_enable => g_with_byte_enable, g_addr_conflict_resolution => g_addr_conflict_resolution, g_init_file => g_init_file, g_fail_if_file_not_found => g_fail_if_file_not_found) port map ( rst_n_i => rst_n_i, clka_i => clka_i, bwea_i => bwea_i, wea_i => wea_i, aa_i => aa_i, da_i => da_i, qa_o => qa_o, clkb_i => clkb_i, bweb_i => bweb_i, web_i => web_i, ab_i => ab_i, db_i => db_i, qb_o => qb_o); end generate gen_dual_clk; end syn;