------------------------------------------------------------------------------- -- -- Copyright 2022 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- -- Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- 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. -- ------------------------------------------------------------------------------- -- Author: Job van Wee -- Purpose: Folding a stream of data into a mm data configuration so it can be -- stored in a DDR RAM-stick. -- -- Description: -- First the data from the sosi array gets collected into one data vector. -- After that this data vector gets resized to the right size data vector in -- order to make it storable in a DDR RAM-stick. -- After that a address gets assigned to the data so the data can be found back. -- -- Remark: -- Use VHDL coding template from: -- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding -- The maximum value of the address is determend by g_tech_ddr. LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib, io_ddr_lib; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; USE technology_lib.technology_pkg.ALL; USE technology_lib.technology_select_pkg.ALL; USE tech_ddr_lib.tech_ddr_pkg.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE io_ddr_lib.ALL; ENTITY ddrctrl IS GENERIC ( g_tech_ddr : t_c_tech_ddr; -- type of memory g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation g_technology : NATURAL := c_tech_select_default; g_nof_streams : NATURAL := 12; -- number of input streams g_data_w : NATURAL := 14; -- data with of input data vectors g_stop_percentage : NATURAL := 50; g_block_size : NATURAL := 1024 ); PORT ( clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; mm_clk : IN STD_LOGIC := '0'; mm_rst : IN STD_LOGIC := '0'; in_sosi_arr : IN t_dp_sosi_arr; -- input data stop_in : IN STD_LOGIC := '0'; out_sosi_arr : OUT t_dp_sosi_arr; term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol; term_ctrl_in : IN t_tech_ddr3_phy_terminationcontrol := c_tech_ddr3_phy_terminationcontrol_rst; -- DDR3 PHY external interface phy3_in : IN t_tech_ddr3_phy_in := c_tech_ddr3_phy_in_x; phy3_io : INOUT t_tech_ddr3_phy_io; phy3_ou : OUT t_tech_ddr3_phy_ou; -- DDR4 PHY external interface phy4_in : IN t_tech_ddr4_phy_in := c_tech_ddr4_phy_in_x; phy4_io : INOUT t_tech_ddr4_phy_io; phy4_ou : OUT t_tech_ddr4_phy_ou ); END ddrctrl; ARCHITECTURE str OF ddrctrl IS -- constant for readability CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); CONSTANT c_wr_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 and independent of wr burst size, default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K CONSTANT c_rd_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 AND > max number of rd burst sizes (so > c_rd_fifo_af_margin), default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K CONSTANT c_rd_fifo_uw_w : NATURAL := ceil_log2(c_rd_fifo_depth*(func_tech_ddr_ctlr_data_w(g_tech_ddr)/c_io_ddr_data_w)); -- signals for connecting the components SIGNAL ctrl_clk : STD_LOGIC; SIGNAL ctrl_rst : STD_LOGIC; SIGNAL out_of : NATURAL := 0; SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL out_adr : NATURAL := 0; SIGNAL dvr_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; SIGNAL dvr_miso : t_mem_ctlr_miso := c_mem_ctlr_miso_rst; SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL rd_siso : t_dp_siso := c_dp_siso_rst; SIGNAL rd_sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL stop : STD_LOGIC; SIGNAL rd_fifo_usedw: STD_LOGIC_VECTOR(c_rd_fifo_uw_w-1 DOWNTO 0); SIGNAL rd_ready : STD_LOGIC; SIGNAL inp_ds : NATURAL; SIGNAL inp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); SIGNAL inp_bsn_adr : NATURAL; SIGNAL outp_ds : NATURAL; SIGNAL outp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); BEGIN rd_siso.ready <= rd_ready; rd_siso.xon <= '1'; -- input to io_ddr u_ddrctrl_input : ENTITY work.ddrctrl_input GENERIC MAP( g_tech_ddr => g_tech_ddr, g_sim_model => g_sim_model, g_nof_streams => g_nof_streams, g_data_w => g_data_w ) PORT MAP( clk => clk, rst => rst, in_sosi_arr => in_sosi_arr, in_stop => stop, out_of => out_of, out_sosi => out_sosi, out_adr => out_adr, out_bsn_ds => inp_ds, out_bsn => inp_bsn, out_bsn_adr => inp_bsn_adr ); -- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick. u_io_ddr : ENTITY io_ddr_lib.io_ddr GENERIC MAP( g_sim_model => g_sim_model, g_technology => g_technology, g_tech_ddr => g_tech_ddr, g_cross_domain_dvr_ctlr => FALSE, g_wr_data_w => c_io_ddr_data_w, g_wr_fifo_depth => c_wr_fifo_depth, g_rd_fifo_depth => c_rd_fifo_depth, g_rd_data_w => c_io_ddr_data_w, g_wr_flush_mode => "VAL", g_wr_flush_use_channel => FALSE, g_wr_flush_start_channel => 0, g_wr_flush_nof_channels => 1 ) PORT MAP( -- DDR reference clock ctlr_ref_clk => clk, ctlr_ref_rst => rst, -- DDR controller clock domain ctlr_clk_out => ctrl_clk, ctlr_rst_out => ctrl_rst, ctlr_clk_in => ctrl_clk, ctlr_rst_in => ctrl_rst, -- MM clock + reset mm_rst => mm_rst, mm_clk => mm_clk, -- MM interface reg_io_ddr_mosi => open, reg_io_ddr_miso => open, -- Driver clock domain dvr_clk => clk, dvr_rst => rst, dvr_miso => dvr_miso, dvr_mosi => dvr_mosi, -- Write FIFO clock domain wr_clk => clk, wr_rst => rst, wr_fifo_usedw => open, wr_sosi => wr_sosi, wr_siso => open, -- Read FIFO clock domain rd_clk => clk, rd_rst => rst, rd_fifo_usedw => rd_fifo_usedw, rd_sosi => rd_sosi, rd_siso => rd_siso, term_ctrl_out => term_ctrl_out, term_ctrl_in => term_ctrl_in, -- DDR3 PHY external interface phy3_in => phy3_in, phy3_io => phy3_io, phy3_ou => phy3_ou, -- DDR4 PHY external interface phy4_in => phy4_in, phy4_io => phy4_io, phy4_ou => phy4_ou ); -- reading ddr memory u_ddrctrl_output : ENTITY work.ddrctrl_output GENERIC MAP( g_tech_ddr => g_tech_ddr, g_sim_model => g_sim_model, g_in_data_w => c_io_ddr_data_w, g_nof_streams => g_nof_streams, g_data_w => g_data_w, g_block_size => g_block_size ) PORT MAP( clk => clk, rst => rst, in_sosi => rd_sosi, in_ds => outp_ds, in_bsn => outp_bsn, out_sosi_arr => out_sosi_arr, out_ready => rd_ready ); -- controller of ddrctrl u_ddrctrl_controller : ENTITY work.ddrctrl_controller GENERIC MAP( g_tech_ddr => g_tech_ddr, g_stop_percentage => g_stop_percentage, g_nof_streams => g_nof_streams, g_out_data_w => g_data_w, g_wr_data_w => c_io_ddr_data_w, g_rd_fifo_depth => c_rd_fifo_depth, g_rd_data_w => c_io_ddr_data_w, g_block_size => g_block_size, g_rd_fifo_uw_w => c_rd_fifo_uw_w ) PORT MAP( clk => clk, rst => rst, -- ddrctrl_input inp_of => out_of, inp_sosi => out_sosi, inp_adr => out_adr, inp_ds => inp_ds, inp_bsn => inp_bsn, inp_bsn_adr => inp_bsn_adr, -- io_ddr dvr_mosi => dvr_mosi, dvr_miso => dvr_miso, wr_sosi => wr_sosi, rd_fifo_usedw => rd_fifo_usedw, -- ddrctrl_output outp_ds => outp_ds, outp_bsn => outp_bsn, -- ddrctrl_controller stop_in => stop_in, stop_out => stop ); END str;