Skip to content
Snippets Groups Projects
Commit 6839c742 authored by David Brouwer's avatar David Brouwer
Browse files

Updated information header e.g.: Changed the remark 'See...

Updated information header e.g.: Changed the remark 'See common_paged_ram_crw_crw for details' to referenced details, because crw_crw is unavailable for Agilex 7 it is illogical to refer to the crw_crw file. Modified to be compatible with Agilex 7. The modification is based on the architecture of common_paged ram_crw_crw.vhd.
parent 76ddb1cb
Branches
No related tags found
1 merge request!363Porting ram for Intel Agilex 7
------------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
-- --
-- Copyright (C) 2011 -- Copyright 2011-2023
-- 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
-- --
-- This program is free software: you can redistribute it and/or modify -- Licensed under the Apache License, Version 2.0 (the "License");
-- it under the terms of the GNU General Public License as published by -- you may not use this file except in compliance with the License.
-- the Free Software Foundation, either version 3 of the License, or -- You may obtain a copy of the License at
-- (at your option) any later version.
-- --
-- This program is distributed in the hope that it will be useful, -- http://www.apache.org/licenses/LICENSE-2.0
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
-- --
-- You should have received a copy of the GNU General Public License -- Unless required by applicable law or agreed to in writing, software
-- along with this program. If not, see <http://www.gnu.org/licenses/>. -- distributed under the 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.
-- --
------------------------------------------------------------------------------- -- -----------------------------------------------------------------------------
--
-- Purpose: Multi page memory -- Author:
-- -
-- Changed by:
-- D.F. Brouwer
-- 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:
-- . See common_paged_ram_crw_crw for details. -- . There are three architecture variants (default use "use_adr"):
-- . use_mux : Use multiplexer logic and one RAM per page
-- . 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
-- . The "use_mux" variant requires the multiplexer logic but can be more
-- efficient regarding RAM usage than the "use_adr" variant.
-- 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
-- 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 crw_crw RAM covers all other variants, which were utilized by other
-- common RAM variant files. However, because the crw_crw IP is no longer
-- supported as it was previously used for previous FPGA technology identifiers
-- (device types) by the Agilex 7 (agi027_xxxx), the rw_rw IP should be used.
-- As a result, this file has been modified. [1]
-- Reference:
-- [1] Based on the architecture of common_paged_ram_crw_crw.vhd.
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_lib; library common_lib;
use work.common_pkg.all; use work.common_pkg.all;
use work.common_mem_pkg.all;
use technology_lib.technology_select_pkg.all; use technology_lib.technology_select_pkg.all;
entity common_paged_ram_rw_rw is entity common_paged_ram_rw_rw is
generic ( generic (
g_technology : natural := c_tech_select_default; g_technology : natural := c_tech_select_default;
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 : in std_logic; rst : in std_logic;
...@@ -65,40 +87,254 @@ entity common_paged_ram_rw_rw is ...@@ -65,40 +87,254 @@ entity common_paged_ram_rw_rw is
); );
end common_paged_ram_rw_rw; end common_paged_ram_rw_rw;
architecture str of common_paged_ram_rw_rw is architecture rtl of common_paged_ram_rw_rw is
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);
-- g_str = "use_mux" :
constant c_page_ram : t_c_mem := (latency => g_rd_latency,
adr_w => c_page_addr_w,
dat_w => g_data_w,
nof_dat => g_page_sz,
init_sl => '0');
type t_data_arr is array (integer range <>) of std_logic_vector(g_data_w - 1 downto 0);
-- g_str = "use_adr" :
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_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,
adr_w => c_mem_addr_w,
dat_w => g_data_w,
nof_dat => c_mem_nof_words,
init_sl => '0');
-- g_str = "use_ofs" :
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_ram : t_c_mem := (latency => g_rd_latency,
adr_w => c_buf_addr_w,
dat_w => g_data_w,
nof_dat => c_buf_nof_words,
init_sl => '0');
-- >>> Page control
-- g_str = "use_mux" and g_str = "use_adr" :
-- . use page_sel direct for wr_en, rd_en, and address
signal page_sel_a : natural range 0 to g_nof_pages - 1;
signal nxt_page_sel_a : natural;
signal page_sel_b : natural range 0 to g_nof_pages - 1;
signal nxt_page_sel_b : natural;
-- . 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 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 nxt_page_sel_b_dly : t_page_sel_arr(0 to g_rd_latency - 1);
-- g_str = "use_ofs" :
signal page_ofs_a : natural range 0 to c_buf_nof_words - 1;
signal nxt_page_ofs_a : natural;
signal page_ofs_b : natural range 0 to c_buf_nof_words - 1;
signal nxt_page_ofs_b : natural;
-- >>> Access control
-- g_str = "use_mux" :
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_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_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_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_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);
-- g_str = "use_adr" :
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);
-- g_str = "use_ofs" :
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);
begin begin
u_crw_crw : entity work.common_paged_ram_crw_crw -- page select (for all) and page address offset (for use_ofs)
generic map ( p_reg_a : process (rst, clk)
g_technology => g_technology, begin
g_str => g_str, if rst = '1' then
g_data_w => g_data_w, page_sel_a <= g_start_page_a;
g_nof_pages => g_nof_pages, page_sel_a_dly <= (others => g_start_page_a);
g_page_sz => g_page_sz, page_ofs_a <= g_start_page_a * g_page_sz;
g_start_page_a => g_start_page_a, elsif rising_edge(clk) then
g_start_page_b => g_start_page_b, page_sel_a <= nxt_page_sel_a;
g_rd_latency => g_rd_latency, page_sel_a_dly <= nxt_page_sel_a_dly;
g_true_dual_port => g_true_dual_port page_ofs_a <= nxt_page_ofs_a;
) end if;
port map ( end process;
rst_a => rst,
rst_b => rst, p_reg_b : process (rst, clk)
clk_a => clk, begin
clk_b => clk, if rst = '1' then
clken_a => clken, page_sel_b <= g_start_page_b;
clken_b => clken, page_sel_b_dly <= (others => g_start_page_b);
next_page_a => next_page_a, page_ofs_b <= g_start_page_b * g_page_sz;
adr_a => adr_a, elsif rising_edge(clk) then
wr_en_a => wr_en_a, page_sel_b <= nxt_page_sel_b;
wr_dat_a => wr_dat_a, page_sel_b_dly <= nxt_page_sel_b_dly;
rd_en_a => rd_en_a, page_ofs_b <= nxt_page_ofs_b;
rd_dat_a => rd_dat_a, end if;
rd_val_a => rd_val_a, end process;
next_page_b => next_page_b,
adr_b => adr_b, nxt_page_sel_a_dly(0) <= page_sel_a;
wr_en_b => wr_en_b, nxt_page_sel_a_dly(1 to g_rd_latency - 1) <= page_sel_a_dly(0 to g_rd_latency - 2);
wr_dat_b => wr_dat_b, nxt_page_sel_b_dly(0) <= page_sel_b;
rd_en_b => rd_en_b, nxt_page_sel_b_dly(1 to g_rd_latency - 1) <= page_sel_b_dly(0 to g_rd_latency - 2);
rd_dat_b => rd_dat_b,
rd_val_b => rd_val_b p_next_page_a : process(next_page_a, page_sel_a, page_ofs_a)
); begin
end str; nxt_page_sel_a <= page_sel_a;
nxt_page_ofs_a <= page_ofs_a;
if next_page_a = '1' then
if page_sel_a < g_nof_pages - 1 then
nxt_page_sel_a <= page_sel_a + 1;
nxt_page_ofs_a <= page_ofs_a + g_page_sz;
else
nxt_page_sel_a <= 0;
nxt_page_ofs_a <= 0;
end if;
end if;
end process;
p_next_page_b : process(next_page_b, page_sel_b, page_ofs_b)
begin
nxt_page_sel_b <= page_sel_b;
nxt_page_ofs_b <= page_ofs_b;
if next_page_b = '1' then
if page_sel_b < g_nof_pages - 1 then
nxt_page_sel_b <= page_sel_b + 1;
nxt_page_ofs_b <= page_ofs_b + g_page_sz;
else
nxt_page_sel_b <= 0;
nxt_page_ofs_b <= 0;
end if;
end if;
end process;
gen_mux : if g_str = "use_mux" generate
gen_pages : for I in 0 to g_nof_pages - 1 generate
u_ram : entity work.common_ram_rw_rw
generic map (
g_technology => g_technology,
g_ram => c_page_ram,
g_init_file => "UNUSED",
g_true_dual_port => g_true_dual_port
)
port map (
rst => rst,
clk => clk,
clken => clken,
adr_a => adr_a,
wr_en_a => page_wr_en_a(I),
wr_dat_a => wr_dat_a,
rd_en_a => page_rd_en_a(I),
rd_dat_a => page_rd_dat_a(I),
rd_val_a => page_rd_val_a(I),
adr_b => adr_b,
wr_en_b => page_wr_en_b(I),
wr_dat_b => wr_dat_b,
rd_en_b => page_rd_en_b(I),
rd_dat_b => page_rd_dat_b(I),
rd_val_b => page_rd_val_b(I)
);
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,
page_sel_b, wr_en_b, rd_en_b, page_sel_b_dly, page_rd_dat_b, page_rd_val_b)
begin
-- use page_sel direct for control
page_wr_en_a <= (others => '0');
page_wr_en_b <= (others => '0');
page_rd_en_a <= (others => '0');
page_rd_en_b <= (others => '0');
page_wr_en_a(page_sel_a) <= wr_en_a;
page_wr_en_b(page_sel_b) <= wr_en_b;
page_rd_en_a(page_sel_a) <= rd_en_a;
page_rd_en_b(page_sel_b) <= rd_en_b;
-- 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_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_b <= page_rd_val_b(page_sel_b_dly(g_rd_latency - 1));
end process;
end generate; -- gen_mux
gen_adr : if g_str = "use_adr" generate
u_mem : entity work.common_ram_rw_rw
generic map (
g_technology => g_technology,
g_ram => c_mem_ram,
g_init_file => "UNUSED",
g_true_dual_port => g_true_dual_port
)
port map (
rst => rst,
clk => clk,
clken => clken,
adr_a => mem_adr_a,
wr_en_a => wr_en_a,
wr_dat_a => wr_dat_a,
rd_en_a => rd_en_a,
rd_dat_a => rd_dat_a,
rd_val_a => rd_val_a,
adr_b => mem_adr_b,
wr_en_b => wr_en_b,
wr_dat_b => wr_dat_b,
rd_en_b => rd_en_b,
rd_dat_b => rd_dat_b,
rd_val_b => rd_val_b
);
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;
end generate; -- gen_adr
gen_ofs : if g_str = "use_ofs" generate
u_buf : entity work.common_ram_rw_rw
generic map (
g_technology => g_technology,
g_ram => c_buf_ram,
g_init_file => "UNUSED",
g_true_dual_port => g_true_dual_port
)
port map (
rst => rst,
clk => clk,
clken => clken,
adr_a => buf_adr_a,
wr_en_a => wr_en_a,
wr_dat_a => wr_dat_a,
rd_en_a => rd_en_a,
rd_dat_a => rd_dat_a,
rd_val_a => rd_val_a,
adr_b => buf_adr_b,
wr_en_b => wr_en_b,
wr_dat_b => wr_dat_b,
rd_en_b => rd_en_b,
rd_dat_b => rd_dat_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_b <= INCR_UVEC(RESIZE_UVEC(adr_b, c_buf_addr_w), page_ofs_b);
end generate; -- gen_ofs
end rtl;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment