-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
--
|
--
|
-- Copyright 2020
|
-- Copyright 2020
|
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
--
|
--
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
-- you may not use this file except in compliance with the License.
|
-- you may not use this file except in compliance with the License.
|
-- You may obtain a copy of the License at
|
-- You may obtain a copy of the License at
|
--
|
--
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
--
|
--
|
-- Unless required by applicable law or agreed to in writing, software
|
-- Unless required by applicable law or agreed to in writing, software
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
-- See the License for the specific language governing permissions and
|
-- See the License for the specific language governing permissions and
|
-- limitations under the License.
|
-- limitations under the License.
|
--
|
--
|
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
|
|
-- Purpose: Multi page memory
|
-- Purpose: Multi page memory
|
-- Description:
|
-- Description:
|
-- When next_page_* pulses then the next access will occur in the next page.
|
-- When next_page_* pulses then the next access will occur in the next page.
|
-- Remarks:
|
-- Remarks:
|
-- . There are three architecture variants (default use "use_adr"):
|
-- . There are three architecture variants (default use "use_adr"):
|
-- . use_mux : Use multiplexer logic and one RAM per page
|
-- . use_mux : Use multiplexer logic and one RAM per page
|
-- . use_adr : Use MSbit address lines and one buf RAM for all pages
|
-- . use_adr : Use MSbit address lines and one buf RAM for all pages
|
-- . use_ofs : Use address offset adders and one buf RAM for all pages
|
-- . use_ofs : Use address offset adders and one buf RAM for all pages
|
-- . The "use_mux" variant requires the multiplexer logic but can be more
|
-- . The "use_mux" variant requires the multiplexer logic but can be more
|
-- efficient regarding RAM usage than the "use_adr" variant.
|
-- efficient regarding RAM usage than the "use_adr" variant.
|
-- The "use_ofs" variant requires address adder logic, but is optimal
|
-- The "use_ofs" variant requires address adder logic, but is optimal
|
-- regarding RAM usage in case the page size is not a power of 2, because the
|
-- regarding RAM usage in case the page size is not a power of 2, because the
|
-- pages are then mapped at subsequent addresses in the buf RAM.
|
-- pages are then mapped at subsequent addresses in the buf RAM.
|
-- . The "use_adr" variant is optimal for speed, so that is set as default.
|
-- . The "use_adr" variant is optimal for speed, so that is set as default.
|
|
|
LIBRARY IEEE, technology_lib;
|
LIBRARY IEEE; --, technology_lib;
|
USE IEEE.std_logic_1164.ALL;
|
USE IEEE.std_logic_1164.ALL;
|
USE IEEE.numeric_std.ALL;
|
USE IEEE.numeric_std.ALL;
|
LIBRARY common_pkg_lib;
|
LIBRARY common_pkg_lib;
|
USE common_pkg_lib.common_pkg.ALL;
|
USE common_pkg_lib.common_pkg.ALL;
|
USE work.common_ram_pkg.ALL;
|
USE work.common_ram_pkg.ALL;
|
USE technology_lib.technology_select_pkg.ALL;
|
-- USE technology_lib.technology_select_pkg.ALL;
|
|
|
ENTITY common_paged_ram_crw_crw IS
|
ENTITY common_paged_ram_crw_crw IS
|
GENERIC (
|
GENERIC (
|
g_technology : NATURAL := c_tech_select_default;
|
g_technology : NATURAL := 0;
|
g_str : STRING := "use_adr";
|
g_str : STRING := "use_adr";
|
g_data_w : NATURAL;
|
g_data_w : NATURAL;
|
g_nof_pages : NATURAL := 2; -- >= 2
|
g_nof_pages : NATURAL := 2; -- >= 2
|
g_page_sz : NATURAL;
|
g_page_sz : NATURAL;
|
g_start_page_a : NATURAL := 0;
|
g_start_page_a : NATURAL := 0;
|
g_start_page_b : NATURAL := 0;
|
g_start_page_b : NATURAL := 0;
|
g_rd_latency : NATURAL := 1;
|
g_rd_latency : NATURAL := 1;
|
g_true_dual_port : BOOLEAN := TRUE
|
g_true_dual_port : BOOLEAN := TRUE
|
);
|
);
|
PORT (
|
PORT (
|
rst_a : IN STD_LOGIC;
|
rst_a : IN STD_LOGIC;
|
rst_b : IN STD_LOGIC;
|
rst_b : IN STD_LOGIC;
|
clk_a : IN STD_LOGIC;
|
clk_a : IN STD_LOGIC;
|
clk_b : IN STD_LOGIC;
|
clk_b : IN STD_LOGIC;
|
clken_a : IN STD_LOGIC := '1';
|
clken_a : IN STD_LOGIC := '1';
|
clken_b : IN STD_LOGIC := '1';
|
clken_b : IN STD_LOGIC := '1';
|
next_page_a : IN STD_LOGIC;
|
next_page_a : IN STD_LOGIC;
|
adr_a : IN STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
|
adr_a : IN STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
|
wr_en_a : IN STD_LOGIC := '0';
|
wr_en_a : IN STD_LOGIC := '0';
|
wr_dat_a : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
|
wr_dat_a : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
|
rd_en_a : IN STD_LOGIC := '1';
|
rd_en_a : IN STD_LOGIC := '1';
|
rd_dat_a : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
rd_dat_a : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
rd_val_a : OUT STD_LOGIC;
|
rd_val_a : OUT STD_LOGIC;
|
next_page_b : IN STD_LOGIC;
|
next_page_b : IN STD_LOGIC;
|
adr_b : IN STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
|
adr_b : IN STD_LOGIC_VECTOR(ceil_log2(g_page_sz)-1 DOWNTO 0) := (OTHERS=>'0');
|
wr_en_b : IN STD_LOGIC := '0';
|
wr_en_b : IN STD_LOGIC := '0';
|
wr_dat_b : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
|
wr_dat_b : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0) := (OTHERS=>'0');
|
rd_en_b : IN STD_LOGIC := '1';
|
rd_en_b : IN STD_LOGIC := '1';
|
rd_dat_b : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
rd_dat_b : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
rd_val_b : OUT STD_LOGIC
|
rd_val_b : OUT STD_LOGIC
|
);
|
);
|
END common_paged_ram_crw_crw;
|
END common_paged_ram_crw_crw;
|
|
|
|
|
ARCHITECTURE rtl OF common_paged_ram_crw_crw IS
|
ARCHITECTURE rtl OF common_paged_ram_crw_crw IS
|
|
|
TYPE t_page_sel_arr IS ARRAY (INTEGER RANGE <>) OF NATURAL RANGE 0 TO g_nof_pages-1;
|
TYPE t_page_sel_arr IS ARRAY (INTEGER RANGE <>) OF NATURAL RANGE 0 TO g_nof_pages-1;
|
|
|
CONSTANT c_page_addr_w : NATURAL := ceil_log2(g_page_sz);
|
CONSTANT c_page_addr_w : NATURAL := ceil_log2(g_page_sz);
|
|
|
-- g_str = "use_mux" :
|
-- g_str = "use_mux" :
|
CONSTANT c_page_ram : t_c_mem := (latency => g_rd_latency,
|
CONSTANT c_page_ram : t_c_mem := (latency => g_rd_latency,
|
adr_w => c_page_addr_w,
|
adr_w => c_page_addr_w,
|
dat_w => g_data_w,
|
dat_w => g_data_w,
|
nof_dat => g_page_sz,
|
nof_dat => g_page_sz,
|
init_sl => '0');
|
init_sl => '0');
|
|
|
TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
TYPE t_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
|
|
|
-- g_str = "use_adr" :
|
-- g_str = "use_adr" :
|
CONSTANT c_mem_nof_pages_w : NATURAL := true_log2(g_nof_pages);
|
CONSTANT c_mem_nof_pages_w : NATURAL := true_log2(g_nof_pages);
|
CONSTANT c_mem_addr_w : NATURAL := c_mem_nof_pages_w + c_page_addr_w;
|
CONSTANT c_mem_addr_w : NATURAL := c_mem_nof_pages_w + c_page_addr_w;
|
CONSTANT c_mem_nof_words : NATURAL := g_nof_pages * 2**c_page_addr_w; -- <= 2**c_mem_addr_w
|
CONSTANT c_mem_nof_words : NATURAL := g_nof_pages * 2**c_page_addr_w; -- <= 2**c_mem_addr_w
|
|
|
CONSTANT c_mem_ram : t_c_mem := (latency => g_rd_latency,
|
CONSTANT c_mem_ram : t_c_mem := (latency => g_rd_latency,
|
adr_w => c_mem_addr_w,
|
adr_w => c_mem_addr_w,
|
dat_w => g_data_w,
|
dat_w => g_data_w,
|
nof_dat => c_mem_nof_words,
|
nof_dat => c_mem_nof_words,
|
init_sl => '0');
|
init_sl => '0');
|
|
|
-- g_str = "use_ofs" :
|
-- g_str = "use_ofs" :
|
CONSTANT c_buf_addr_w : NATURAL := ceil_log2(g_nof_pages * g_page_sz);
|
CONSTANT c_buf_addr_w : NATURAL := ceil_log2(g_nof_pages * g_page_sz);
|
CONSTANT c_buf_nof_words : NATURAL := g_nof_pages * g_page_sz;
|
CONSTANT c_buf_nof_words : NATURAL := g_nof_pages * g_page_sz;
|
|
|
CONSTANT c_buf_ram : t_c_mem := (latency => g_rd_latency,
|
CONSTANT c_buf_ram : t_c_mem := (latency => g_rd_latency,
|
adr_w => c_buf_addr_w,
|
adr_w => c_buf_addr_w,
|
dat_w => g_data_w,
|
dat_w => g_data_w,
|
nof_dat => c_buf_nof_words,
|
nof_dat => c_buf_nof_words,
|
init_sl => '0');
|
init_sl => '0');
|
|
|
-- >>> Page control
|
-- >>> Page control
|
|
|
-- g_str = "use_mux" and g_str = "use_adr" :
|
-- g_str = "use_mux" and g_str = "use_adr" :
|
-- . use page_sel direct for wr_en, rd_en, and address
|
-- . use page_sel direct for wr_en, rd_en, and address
|
SIGNAL page_sel_a : NATURAL RANGE 0 TO g_nof_pages-1;
|
SIGNAL page_sel_a : NATURAL RANGE 0 TO g_nof_pages-1;
|
SIGNAL nxt_page_sel_a : NATURAL;
|
SIGNAL nxt_page_sel_a : NATURAL;
|
SIGNAL page_sel_b : NATURAL RANGE 0 TO g_nof_pages-1;
|
SIGNAL page_sel_b : NATURAL RANGE 0 TO g_nof_pages-1;
|
SIGNAL nxt_page_sel_b : NATURAL;
|
SIGNAL nxt_page_sel_b : NATURAL;
|
|
|
-- . use page_sel_dly to adjust for g_rd_latency of rd_dat and rd_val
|
-- . use page_sel_dly to adjust for g_rd_latency of rd_dat and rd_val
|
SIGNAL page_sel_a_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL page_sel_a_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL nxt_page_sel_a_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL nxt_page_sel_a_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL page_sel_b_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL page_sel_b_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL nxt_page_sel_b_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
SIGNAL nxt_page_sel_b_dly : t_page_sel_arr(0 TO g_rd_latency-1);
|
|
|
-- g_str = "use_ofs" :
|
-- g_str = "use_ofs" :
|
SIGNAL page_ofs_a : NATURAL RANGE 0 TO c_buf_nof_words-1;
|
SIGNAL page_ofs_a : NATURAL RANGE 0 TO c_buf_nof_words-1;
|
SIGNAL nxt_page_ofs_a : NATURAL;
|
SIGNAL nxt_page_ofs_a : NATURAL;
|
SIGNAL page_ofs_b : NATURAL RANGE 0 TO c_buf_nof_words-1;
|
SIGNAL page_ofs_b : NATURAL RANGE 0 TO c_buf_nof_words-1;
|
SIGNAL nxt_page_ofs_b : NATURAL;
|
SIGNAL nxt_page_ofs_b : NATURAL;
|
|
|
-- >>> Access control
|
-- >>> Access control
|
|
|
-- g_str = "use_mux" :
|
-- g_str = "use_mux" :
|
SIGNAL page_wr_en_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_wr_en_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_wr_dat_a : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_wr_dat_a : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_en_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_en_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_dat_a : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_dat_a : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_val_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_val_a : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
|
|
SIGNAL page_wr_en_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_wr_en_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_wr_dat_b : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_wr_dat_b : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_en_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_en_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_dat_b : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_dat_b : t_data_arr(0 TO g_nof_pages-1);
|
SIGNAL page_rd_val_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
SIGNAL page_rd_val_b : STD_LOGIC_VECTOR(0 TO g_nof_pages-1);
|
|
|
-- g_str = "use_adr" :
|
-- g_str = "use_adr" :
|
SIGNAL mem_adr_a : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
|
SIGNAL mem_adr_a : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
|
SIGNAL mem_adr_b : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
|
SIGNAL mem_adr_b : STD_LOGIC_VECTOR(c_mem_addr_w-1 DOWNTO 0);
|
|
|
-- g_str = "use_ofs" :
|
-- g_str = "use_ofs" :
|
SIGNAL buf_adr_a : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
|
SIGNAL buf_adr_a : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
|
SIGNAL buf_adr_b : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
|
SIGNAL buf_adr_b : STD_LOGIC_VECTOR(c_buf_addr_w-1 DOWNTO 0);
|
|
|
BEGIN
|
BEGIN
|
|
|
-- page select (for all) and page address offset (for use_ofs)
|
-- page select (for all) and page address offset (for use_ofs)
|
p_reg_a : PROCESS (rst_a, clk_a)
|
p_reg_a : PROCESS (rst_a, clk_a)
|
BEGIN
|
BEGIN
|
IF rst_a = '1' THEN
|
IF rst_a = '1' THEN
|
page_sel_a <= g_start_page_a;
|
page_sel_a <= g_start_page_a;
|
page_sel_a_dly <= (OTHERS=>g_start_page_a);
|
page_sel_a_dly <= (OTHERS=>g_start_page_a);
|
page_ofs_a <= g_start_page_a * g_page_sz;
|
page_ofs_a <= g_start_page_a * g_page_sz;
|
ELSIF rising_edge(clk_a) THEN
|
ELSIF rising_edge(clk_a) THEN
|
page_sel_a <= nxt_page_sel_a;
|
page_sel_a <= nxt_page_sel_a;
|
page_sel_a_dly <= nxt_page_sel_a_dly;
|
page_sel_a_dly <= nxt_page_sel_a_dly;
|
page_ofs_a <= nxt_page_ofs_a;
|
page_ofs_a <= nxt_page_ofs_a;
|
END IF;
|
END IF;
|
END PROCESS;
|
END PROCESS;
|
|
|
p_reg_b : PROCESS (rst_b, clk_b)
|
p_reg_b : PROCESS (rst_b, clk_b)
|
BEGIN
|
BEGIN
|
IF rst_b = '1' THEN
|
IF rst_b = '1' THEN
|
page_sel_b <= g_start_page_b;
|
page_sel_b <= g_start_page_b;
|
page_sel_b_dly <= (OTHERS=>g_start_page_b);
|
page_sel_b_dly <= (OTHERS=>g_start_page_b);
|
page_ofs_b <= g_start_page_b * g_page_sz;
|
page_ofs_b <= g_start_page_b * g_page_sz;
|
ELSIF rising_edge(clk_b) THEN
|
ELSIF rising_edge(clk_b) THEN
|
page_sel_b <= nxt_page_sel_b;
|
page_sel_b <= nxt_page_sel_b;
|
page_sel_b_dly <= nxt_page_sel_b_dly;
|
page_sel_b_dly <= nxt_page_sel_b_dly;
|
page_ofs_b <= nxt_page_ofs_b;
|
page_ofs_b <= nxt_page_ofs_b;
|
END IF;
|
END IF;
|
END PROCESS;
|
END PROCESS;
|
|
|
nxt_page_sel_a_dly(0) <= page_sel_a;
|
nxt_page_sel_a_dly(0) <= page_sel_a;
|
nxt_page_sel_a_dly(1 TO g_rd_latency-1) <= page_sel_a_dly(0 TO g_rd_latency-2);
|
nxt_page_sel_a_dly(1 TO g_rd_latency-1) <= page_sel_a_dly(0 TO g_rd_latency-2);
|
nxt_page_sel_b_dly(0) <= page_sel_b;
|
nxt_page_sel_b_dly(0) <= page_sel_b;
|
nxt_page_sel_b_dly(1 TO g_rd_latency-1) <= page_sel_b_dly(0 TO g_rd_latency-2);
|
nxt_page_sel_b_dly(1 TO g_rd_latency-1) <= page_sel_b_dly(0 TO g_rd_latency-2);
|
|
|
p_next_page_a : PROCESS(next_page_a, page_sel_a, page_ofs_a)
|
p_next_page_a : PROCESS(next_page_a, page_sel_a, page_ofs_a)
|
BEGIN
|
BEGIN
|
nxt_page_sel_a <= page_sel_a;
|
nxt_page_sel_a <= page_sel_a;
|
nxt_page_ofs_a <= page_ofs_a;
|
nxt_page_ofs_a <= page_ofs_a;
|
IF next_page_a='1' THEN
|
IF next_page_a='1' THEN
|
IF page_sel_a < g_nof_pages-1 THEN
|
IF page_sel_a < g_nof_pages-1 THEN
|
nxt_page_sel_a <= page_sel_a + 1;
|
nxt_page_sel_a <= page_sel_a + 1;
|
nxt_page_ofs_a <= page_ofs_a + g_page_sz;
|
nxt_page_ofs_a <= page_ofs_a + g_page_sz;
|
ELSE
|
ELSE
|
nxt_page_sel_a <= 0;
|
nxt_page_sel_a <= 0;
|
nxt_page_ofs_a <= 0;
|
nxt_page_ofs_a <= 0;
|
END IF;
|
END IF;
|
END IF;
|
END IF;
|
END PROCESS;
|
END PROCESS;
|
|
|
p_next_page_b : PROCESS(next_page_b, page_sel_b, page_ofs_b)
|
p_next_page_b : PROCESS(next_page_b, page_sel_b, page_ofs_b)
|
BEGIN
|
BEGIN
|
nxt_page_sel_b <= page_sel_b;
|
nxt_page_sel_b <= page_sel_b;
|
nxt_page_ofs_b <= page_ofs_b;
|
nxt_page_ofs_b <= page_ofs_b;
|
IF next_page_b='1' THEN
|
IF next_page_b='1' THEN
|
IF page_sel_b < g_nof_pages-1 THEN
|
IF page_sel_b < g_nof_pages-1 THEN
|
nxt_page_sel_b <= page_sel_b + 1;
|
nxt_page_sel_b <= page_sel_b + 1;
|
nxt_page_ofs_b <= page_ofs_b + g_page_sz;
|
nxt_page_ofs_b <= page_ofs_b + g_page_sz;
|
ELSE
|
ELSE
|
nxt_page_sel_b <= 0;
|
nxt_page_sel_b <= 0;
|
nxt_page_ofs_b <= 0;
|
nxt_page_ofs_b <= 0;
|
END IF;
|
END IF;
|
END IF;
|
END IF;
|
END PROCESS;
|
END PROCESS;
|
|
|
|
|
gen_mux : IF g_str = "use_mux" GENERATE
|
gen_mux : IF g_str = "use_mux" GENERATE
|
gen_pages : FOR I IN 0 TO g_nof_pages-1 GENERATE
|
gen_pages : FOR I IN 0 TO g_nof_pages-1 GENERATE
|
u_ram : ENTITY work.common_ram_crw_crw
|
u_ram : ENTITY work.common_ram_crw_crw
|
GENERIC MAP (
|
GENERIC MAP (
|
g_technology => g_technology,
|
g_technology => g_technology,
|
g_ram => c_page_ram,
|
g_ram => c_page_ram,
|
g_init_file => "UNUSED",
|
g_init_file => "UNUSED",
|
g_true_dual_port => g_true_dual_port
|
g_true_dual_port => g_true_dual_port
|
)
|
)
|
PORT MAP (
|
PORT MAP (
|
rst_a => rst_a,
|
rst_a => rst_a,
|
rst_b => rst_b,
|
rst_b => rst_b,
|
clk_a => clk_a,
|
clk_a => clk_a,
|
clk_b => clk_b,
|
clk_b => clk_b,
|
clken_a => clken_a,
|
clken_a => clken_a,
|
clken_b => clken_b,
|
clken_b => clken_b,
|
adr_a => adr_a,
|
adr_a => adr_a,
|
wr_en_a => page_wr_en_a(I),
|
wr_en_a => page_wr_en_a(I),
|
wr_dat_a => wr_dat_a,
|
wr_dat_a => wr_dat_a,
|
rd_en_a => page_rd_en_a(I),
|
rd_en_a => page_rd_en_a(I),
|
rd_dat_a => page_rd_dat_a(I),
|
rd_dat_a => page_rd_dat_a(I),
|
rd_val_a => page_rd_val_a(I),
|
rd_val_a => page_rd_val_a(I),
|
adr_b => adr_b,
|
adr_b => adr_b,
|
wr_en_b => page_wr_en_b(I),
|
wr_en_b => page_wr_en_b(I),
|
wr_dat_b => wr_dat_b,
|
wr_dat_b => wr_dat_b,
|
rd_en_b => page_rd_en_b(I),
|
rd_en_b => page_rd_en_b(I),
|
rd_dat_b => page_rd_dat_b(I),
|
rd_dat_b => page_rd_dat_b(I),
|
rd_val_b => page_rd_val_b(I)
|
rd_val_b => page_rd_val_b(I)
|
);
|
);
|
END GENERATE;
|
END GENERATE;
|
|
|
p_mux : PROCESS(page_sel_a, wr_en_a, rd_en_a, page_sel_a_dly, page_rd_dat_a, page_rd_val_a,
|
p_mux : PROCESS(page_sel_a, wr_en_a, rd_en_a, page_sel_a_dly, page_rd_dat_a, page_rd_val_a,
|
page_sel_b, wr_en_b, rd_en_b, page_sel_b_dly, page_rd_dat_b, page_rd_val_b)
|
page_sel_b, wr_en_b, rd_en_b, page_sel_b_dly, page_rd_dat_b, page_rd_val_b)
|
BEGIN
|
BEGIN
|
-- use page_sel direct for control
|
-- use page_sel direct for control
|
page_wr_en_a <= (OTHERS=>'0');
|
page_wr_en_a <= (OTHERS=>'0');
|
page_wr_en_b <= (OTHERS=>'0');
|
page_wr_en_b <= (OTHERS=>'0');
|
page_rd_en_a <= (OTHERS=>'0');
|
page_rd_en_a <= (OTHERS=>'0');
|
page_rd_en_b <= (OTHERS=>'0');
|
page_rd_en_b <= (OTHERS=>'0');
|
page_wr_en_a(page_sel_a) <= wr_en_a;
|
page_wr_en_a(page_sel_a) <= wr_en_a;
|
page_wr_en_b(page_sel_b) <= wr_en_b;
|
page_wr_en_b(page_sel_b) <= wr_en_b;
|
page_rd_en_a(page_sel_a) <= rd_en_a;
|
page_rd_en_a(page_sel_a) <= rd_en_a;
|
page_rd_en_b(page_sel_b) <= rd_en_b;
|
page_rd_en_b(page_sel_b) <= rd_en_b;
|
|
|
-- use page_sel_dly to account for the RAM read latency
|
-- use page_sel_dly to account for the RAM read latency
|
rd_dat_a <= page_rd_dat_a(page_sel_a_dly(g_rd_latency-1));
|
rd_dat_a <= page_rd_dat_a(page_sel_a_dly(g_rd_latency-1));
|
rd_dat_b <= page_rd_dat_b(page_sel_b_dly(g_rd_latency-1));
|
rd_dat_b <= page_rd_dat_b(page_sel_b_dly(g_rd_latency-1));
|
rd_val_a <= page_rd_val_a(page_sel_a_dly(g_rd_latency-1));
|
rd_val_a <= page_rd_val_a(page_sel_a_dly(g_rd_latency-1));
|
rd_val_b <= page_rd_val_b(page_sel_b_dly(g_rd_latency-1));
|
rd_val_b <= page_rd_val_b(page_sel_b_dly(g_rd_latency-1));
|
END PROCESS;
|
END PROCESS;
|
END GENERATE; -- gen_mux
|
END GENERATE; -- gen_mux
|
|
|
gen_adr : IF g_str = "use_adr" GENERATE
|
gen_adr : IF g_str = "use_adr" GENERATE
|
u_mem : ENTITY work.common_ram_crw_crw
|
u_mem : ENTITY work.common_ram_crw_crw
|
GENERIC MAP (
|
GENERIC MAP (
|
g_technology => g_technology,
|
g_technology => g_technology,
|
g_ram => c_mem_ram,
|
g_ram => c_mem_ram,
|
g_init_file => "UNUSED",
|
g_init_file => "UNUSED",
|
g_true_dual_port => g_true_dual_port
|
g_true_dual_port => g_true_dual_port
|
)
|
)
|
PORT MAP (
|
PORT MAP (
|
rst_a => rst_a,
|
rst_a => rst_a,
|
rst_b => rst_b,
|
rst_b => rst_b,
|
clk_a => clk_a,
|
clk_a => clk_a,
|
clk_b => clk_b,
|
clk_b => clk_b,
|
clken_a => clken_a,
|
clken_a => clken_a,
|
clken_b => clken_b,
|
clken_b => clken_b,
|
adr_a => mem_adr_a,
|
adr_a => mem_adr_a,
|
wr_en_a => wr_en_a,
|
wr_en_a => wr_en_a,
|
wr_dat_a => wr_dat_a,
|
wr_dat_a => wr_dat_a,
|
rd_en_a => rd_en_a,
|
rd_en_a => rd_en_a,
|
rd_dat_a => rd_dat_a,
|
rd_dat_a => rd_dat_a,
|
rd_val_a => rd_val_a,
|
rd_val_a => rd_val_a,
|
adr_b => mem_adr_b,
|
adr_b => mem_adr_b,
|
wr_en_b => wr_en_b,
|
wr_en_b => wr_en_b,
|
wr_dat_b => wr_dat_b,
|
wr_dat_b => wr_dat_b,
|
rd_en_b => rd_en_b,
|
rd_en_b => rd_en_b,
|
rd_dat_b => rd_dat_b,
|
rd_dat_b => rd_dat_b,
|
rd_val_b => rd_val_b
|
rd_val_b => rd_val_b
|
);
|
);
|
|
|
mem_adr_a <= TO_UVEC(page_sel_a, c_mem_nof_pages_w) & adr_a;
|
mem_adr_a <= TO_UVEC(page_sel_a, c_mem_nof_pages_w) & adr_a;
|
mem_adr_b <= TO_UVEC(page_sel_b, c_mem_nof_pages_w) & adr_b;
|
mem_adr_b <= TO_UVEC(page_sel_b, c_mem_nof_pages_w) & adr_b;
|
END GENERATE; -- gen_adr
|
END GENERATE; -- gen_adr
|
|
|
|
|
gen_ofs : IF g_str = "use_ofs" GENERATE
|
gen_ofs : IF g_str = "use_ofs" GENERATE
|
u_buf : ENTITY work.common_ram_crw_crw
|
u_buf : ENTITY work.common_ram_crw_crw
|
GENERIC MAP (
|
GENERIC MAP (
|
g_technology => g_technology,
|
g_technology => g_technology,
|
g_ram => c_buf_ram,
|
g_ram => c_buf_ram,
|
g_init_file => "UNUSED",
|
g_init_file => "UNUSED",
|
g_true_dual_port => g_true_dual_port
|
g_true_dual_port => g_true_dual_port
|
)
|
)
|
PORT MAP (
|
PORT MAP (
|
rst_a => rst_a,
|
rst_a => rst_a,
|
rst_b => rst_b,
|
rst_b => rst_b,
|
clk_a => clk_a,
|
clk_a => clk_a,
|
clk_b => clk_b,
|
clk_b => clk_b,
|
clken_a => clken_a,
|
clken_a => clken_a,
|
clken_b => clken_b,
|
clken_b => clken_b,
|
adr_a => buf_adr_a,
|
adr_a => buf_adr_a,
|
wr_en_a => wr_en_a,
|
wr_en_a => wr_en_a,
|
wr_dat_a => wr_dat_a,
|
wr_dat_a => wr_dat_a,
|
rd_en_a => rd_en_a,
|
rd_en_a => rd_en_a,
|
rd_dat_a => rd_dat_a,
|
rd_dat_a => rd_dat_a,
|
rd_val_a => rd_val_a,
|
rd_val_a => rd_val_a,
|
adr_b => buf_adr_b,
|
adr_b => buf_adr_b,
|
wr_en_b => wr_en_b,
|
wr_en_b => wr_en_b,
|
wr_dat_b => wr_dat_b,
|
wr_dat_b => wr_dat_b,
|
rd_en_b => rd_en_b,
|
rd_en_b => rd_en_b,
|
rd_dat_b => rd_dat_b,
|
rd_dat_b => rd_dat_b,
|
rd_val_b => rd_val_b
|
rd_val_b => rd_val_b
|
);
|
);
|
|
|
buf_adr_a <= INCR_UVEC(RESIZE_UVEC(adr_a, c_buf_addr_w), page_ofs_a);
|
buf_adr_a <= INCR_UVEC(RESIZE_UVEC(adr_a, c_buf_addr_w), page_ofs_a);
|
buf_adr_b <= INCR_UVEC(RESIZE_UVEC(adr_b, c_buf_addr_w), page_ofs_b);
|
buf_adr_b <= INCR_UVEC(RESIZE_UVEC(adr_b, c_buf_addr_w), page_ofs_b);
|
END GENERATE; -- gen_ofs
|
END GENERATE; -- gen_ofs
|
|
|
END rtl;
|
END rtl;
|
|
|