An error occurred while loading the file. Please try again.
-
Dimitris Lampridis authorede7c5ad9f
generic_dpram.vhd 8.69 KiB
--------------------------------------------------------------------------------
-- 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;