From 27c93f512a65eaf724ad23f5d6fcce2e4e196118 Mon Sep 17 00:00:00 2001 From: JobvanWee <wee@astron.nl> Date: Wed, 6 Apr 2022 17:27:12 +0200 Subject: [PATCH] IT works!! --- .../lofar2/libraries/ddrctrl/hdllib.cfg | 3 + .../libraries/ddrctrl/src/vhdl/ddrctrl.vhd | 83 ++++++-- .../ddrctrl/src/vhdl/ddrctrl_controller.vhd | 184 ++++++++++++++++-- .../ddrctrl/src/vhdl/ddrctrl_input.vhd | 2 +- .../ddrctrl/src/vhdl/ddrctrl_output.vhd | 103 ++++++++++ .../src/vhdl/ddrctrl_output_repack.vhd | 58 ++++++ .../src/vhdl/ddrctrl_output_unpack.vhd | 173 ++++++++++++++++ .../libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd | 2 + 8 files changed, 573 insertions(+), 35 deletions(-) create mode 100644 applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd create mode 100644 applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd create mode 100644 applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd diff --git a/applications/lofar2/libraries/ddrctrl/hdllib.cfg b/applications/lofar2/libraries/ddrctrl/hdllib.cfg index dc978140ea..e399eb4af6 100644 --- a/applications/lofar2/libraries/ddrctrl/hdllib.cfg +++ b/applications/lofar2/libraries/ddrctrl/hdllib.cfg @@ -9,6 +9,9 @@ synth_files = src/vhdl/ddrctrl_input_pack.vhd src/vhdl/ddrctrl_input_repack.vhd src/vhdl/ddrctrl_input.vhd + src/vhdl/ddrctrl_output_unpack.vhd + src/vhdl/ddrctrl_output_repack.vhd + src/vhdl/ddrctrl_output.vhd src/vhdl/ddrctrl_controller.vhd src/vhdl/ddrctrl.vhd diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 25ce70e55c..e7de428b6c 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -62,6 +62,7 @@ ENTITY ddrctrl IS wr_not_rd : IN STD_LOGIC := '0'; 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; @@ -93,13 +94,24 @@ ARCHITECTURE str OF ddrctrl IS 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(ceil_log2(c_rd_fifo_depth*(func_tech_ddr_ctlr_data_w(g_tech_ddr)/c_io_ddr_data_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 @@ -116,7 +128,10 @@ BEGIN in_stop => stop, out_of => out_of, out_sosi => out_sosi, - out_adr => out_adr + 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. @@ -160,7 +175,7 @@ BEGIN dvr_clk => clk, dvr_rst => rst, - dvr_miso => open, + dvr_miso => dvr_miso, dvr_mosi => dvr_mosi, -- Write FIFO clock domain @@ -175,8 +190,8 @@ BEGIN rd_clk => clk, rd_rst => rst, - rd_fifo_usedw => open, - rd_sosi => open, + rd_fifo_usedw => rd_fifo_usedw, + rd_sosi => rd_sosi, rd_siso => rd_siso, term_ctrl_out => term_ctrl_out, @@ -193,26 +208,62 @@ BEGIN 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_nof_streams => g_nof_streams, + g_data_w => g_data_w + ) + 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_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 ) PORT MAP( - clk => clk, - rst => rst, - - out_of => out_of, - out_sosi => out_sosi, - out_adr => out_adr, + clk => clk, + rst => rst, + + -- ddrctrl_input + out_of => out_of, + out_sosi => out_sosi, + out_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, - dvr_mosi => dvr_mosi, - wr_sosi => wr_sosi, - rd_siso => rd_siso, + -- ddrctrl_output + outp_ds => outp_ds, + outp_bsn => outp_bsn, - stop_in => stop_in, - stop_out => stop + -- ddrctrl_controller + stop_in => stop_in, + stop_out => stop ); END str; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd index f9e9548fc7..378efd0b61 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_controller.vhd @@ -39,7 +39,12 @@ USE tech_ddr_lib.tech_ddr_pkg.ALL; ENTITY ddrctrl_controller IS GENERIC ( g_tech_ddr : t_c_tech_ddr; - g_stop_percentage : NATURAL := 50 + g_stop_percentage : NATURAL := 50; + g_nof_streams : NATURAL; + g_out_data_w : NATURAL; + g_wr_data_w : NATURAL; + g_rd_fifo_depth : NATURAL; + g_rd_data_w : NATURAL ); PORT ( clk : IN STD_LOGIC; @@ -49,13 +54,21 @@ ENTITY ddrctrl_controller IS out_of : IN NATURAL; out_sosi : IN t_dp_sosi; out_adr : IN NATURAL; + inp_ds : IN NATURAL; + inp_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + inp_bsn_adr : IN NATURAL; -- io_ddr dvr_mosi : OUT t_mem_ctlr_mosi; + dvr_miso : IN t_mem_ctlr_miso; wr_sosi : OUT t_dp_sosi; - rd_siso : OUT t_dp_siso; + rd_fifo_usedw : IN STD_LOGIC_VECTOR(ceil_log2(g_rd_fifo_depth * (func_tech_ddr_ctlr_data_w(g_tech_ddr)/g_rd_data_w) )-1 DOWNTO 0); - -- ddrctrl + -- ddrctrl_output + outp_ds : OUT NATURAL; + outp_bsn : OUT STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); + + -- ddrctrl_controller stop_in : IN STD_LOGIC; stop_out : OUT STD_LOGIC ); @@ -70,25 +83,39 @@ ARCHITECTURE rtl OF ddrctrl_controller IS CONSTANT c_pof_ma : NATURAL := (c_max_adr*(100-g_stop_percentage))/100; CONSTANT c_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-1 DOWNTO 0) := (OTHERS => '0'); + -- constant for reading + CONSTANT c_rd_data_w : NATURAL := g_nof_streams*g_out_data_w; -- 168 + CONSTANT c_rest : NATURAL := c_rd_data_w-(g_wr_data_w mod c_rd_data_w); -- 96 + CONSTANT c_max_read_cnt : NATURAL := (c_max_adr+1)/c_burstsize; -- 256 + + -- not needed hopefully + --CONSTANT c_gcd : NATURAL := GCD(c_rd_data_w, g_wr_data_w); -- 24 + --CONSTANT c_ofset_repeat : NATURAL := c_rd_data_wc/c_gcd; -- 7 + -- type for statemachine - TYPE t_state IS (RESET, WRITING, SET_STOP, STOP_WRITING, READING, STOP_READING, IDLE); + TYPE t_state IS (RESET, WRITING, SET_STOP, STOP_WRITING, START_READING, READING, STOP_READING, IDLE); -- record for readability TYPE t_reg IS RECORD -- state of program state : t_state; - -- signals + -- stoppping signals stop_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); stopped : STD_LOGIC; + -- reading signals + outp_ds : NATURAL; + outp_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + read_cnt : NATURAL; + rd_burst_en : STD_LOGIC; + -- output dvr_mosi : t_mem_ctlr_mosi; wr_sosi : t_dp_sosi; - rd_siso : t_dp_siso; END RECORD; - CONSTANT c_t_reg_init : t_reg := (RESET, TO_UVEC(c_max_adr, c_adr_w), '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init, c_dp_siso_rst); + CONSTANT c_t_reg_init : t_reg := (RESET, TO_UVEC(c_max_adr, c_adr_w), '0', 0, (OTHERS => '0'), 0, '0', c_mem_ctlr_mosi_rst, c_dp_sosi_init); -- signals for readability @@ -100,20 +127,30 @@ BEGIN q_reg <= d_reg WHEN rising_edge(clk); -- put the input data into c_v and fill the output vector from c_v - p_state : PROCESS(q_reg, rst, out_of, out_sosi, out_adr) + p_state : PROCESS(q_reg, rst, out_of, out_sosi, out_adr, dvr_miso, rd_fifo_usedw) VARIABLE v : t_reg := c_t_reg_init; BEGIN v := q_reg; - CASE q_reg.state IS - - + CASE q_reg.state IS WHEN RESET => v := c_t_reg_init; + IF rst = '1' THEN + v.state := RESET; + ELSIF stop_in = '1' THEN + v.state := SET_STOP; + ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + v.state := STOP_WRITING; + ELSIF v.stopped = '1' THEN + v.state := IDLE; + ELSE + v.state := WRITING; + END IF; + WHEN WRITING => IF TO_UVEC(out_adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN -- if adr mod c_burstsize = 0 @@ -133,6 +170,19 @@ BEGIN + IF rst = '1' THEN + v.state := RESET; + ELSIF stop_in = '1' THEN + v.state := SET_STOP; + ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + v.state := STOP_WRITING; + ELSIF v.stopped = '1' THEN + v.state := IDLE; + ELSE + v.state := WRITING; + END IF; + + WHEN SET_STOP => --setting a stop address dependend on the g_stop_percentage IF out_adr+c_pof_ma >= c_max_adr THEN @@ -160,13 +210,105 @@ BEGIN + IF rst = '1' THEN + v.state := RESET; + ELSIF stop_in = '1' THEN + v.state := SET_STOP; + ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + v.state := STOP_WRITING; + ELSIF v.stopped = '1' THEN + v.state := IDLE; + ELSE + v.state := WRITING; + END IF; + + WHEN STOP_WRITING => - v.stopped := '1'; - v.wr_sosi.valid := '0'; - v.dvr_mosi.flush := '1'; + v.dvr_mosi.burstbegin := '0'; + IF dvr_miso.done = '1' THEN -- wait until the write burst is finished + v.stopped := '1'; + v.wr_sosi.valid := '0'; + v.dvr_mosi.flush := '1'; + v.state := START_READING; + ELSE + v.state := STOP_WRITING; + END IF; + + + IF rst = '1' THEN + v.state := RESET; + END IF; + + + WHEN START_READING => + v.rd_burst_en := '1'; + v.dvr_mosi.wr := '0'; + v.dvr_mosi.rd := '1'; + v.outp_ds := inp_ds; + + FOR I IN 0 TO inp_bsn_adr+(c_max_adr-TO_UINT(q_reg.stop_adr)) LOOP -- takes a while + IF v.outp_ds-c_rest <= 0 THEN + v.outp_ds := v.outp_ds+c_rd_data_w-c_rest; + ELSE + v.outp_ds := v.outp_ds-c_rest; + END IF; + END LOOP; + + v.outp_bsn := TO_UVEC(TO_UINT(inp_bsn)-((inp_bsn_adr+(c_max_adr-TO_UINT(q_reg.stop_adr)))*g_wr_data_w+v.outp_ds-inp_ds)/c_rd_data_w, c_dp_stream_bsn_w); -- maths + + + IF rst = '1' THEN + v.state := RESET; + ELSE + v.state := READING; + END IF; + + + WHEN READING => + + IF TO_UINT(rd_fifo_usedw) = 0 AND dvr_miso.done = '1' AND q_reg.rd_burst_en = '1' THEN + IF TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt >= c_max_adr THEN + v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr, c_adr_w); + --assert false report "1. address: " & natural'image((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)-c_max_adr) severity note; + ELSE + v.dvr_mosi.address(c_adr_w-1 DOWNTO 0) := TO_UVEC(TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt, c_adr_w); + --assert false report "2. address: " & natural'image((TO_UINT(q_reg.stop_adr(c_adr_w-1 DOWNTO 0))+c_burstsize*q_reg.read_cnt)) severity note; + END IF; + v.dvr_mosi.burstbegin := '1'; + v.read_cnt := v.read_cnt+1; + v.rd_burst_en := '0'; + ELSE + v.dvr_mosi.burstbegin := '0'; + END IF; + + IF TO_UINT(rd_fifo_usedw) >= 1 THEN + v.rd_burst_en := '1'; + END IF; + + IF rst = '1' THEN + v.state := RESET; + ELSIF q_reg.read_cnt >= c_max_read_cnt THEN + v.state := IDLE; + ELSE + v.state := READING; + END IF; + WHEN IDLE => - + + + + IF rst = '1' THEN + v.state := RESET; + ELSIF stop_in = '1' THEN + v.state := SET_STOP; + ELSIF v.stop_adr = TO_UVEC(out_adr, c_adr_w) AND v.stop_adr(c_bitshift_adr-1 DOWNTO 0) = c_zeros(c_bitshift_adr-1 DOWNTO 0) AND q_reg.stopped = '0' THEN + v.state := STOP_WRITING; + ELSIF v.stopped = '1' THEN + v.state := IDLE; + ELSE + v.state := WRITING; + END IF; WHEN OTHERS => @@ -174,8 +316,6 @@ BEGIN - END CASE; - IF rst = '1' THEN v.state := RESET; ELSIF stop_in = '1' THEN @@ -187,13 +327,21 @@ BEGIN ELSE v.state := WRITING; END IF; + + + END CASE; + + + d_reg <= v; + END PROCESS; -- fill outputs dvr_mosi <= q_reg.dvr_mosi; wr_sosi <= q_reg.wr_sosi; - rd_siso <= q_reg.rd_siso; stop_out <= q_reg.stopped; + outp_bsn <= q_reg.outp_bsn; + outp_ds <= q_reg.outp_ds; END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd index 88b7e492bf..e08d57fcd7 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_input.vhd @@ -53,7 +53,7 @@ ENTITY ddrctrl_input IS clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; in_sosi_arr : IN t_dp_sosi_arr; -- input data - in_stop : IN STD_LOGIC; + in_stop : IN STD_LOGIC; out_of : OUT NATURAL; -- amount of internal overflow this output out_sosi : OUT t_dp_sosi; -- output data out_adr : OUT NATURAL; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd new file mode 100644 index 0000000000..cc934f3a06 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output.vhd @@ -0,0 +1,103 @@ +------------------------------------------------------------------------------- +-- +-- 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; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE technology_lib.technology_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; + + +ENTITY ddrctrl_output IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_in_data_w : NATURAL := 576; + g_nof_streams : NATURAL := 12; -- number of input streams + g_data_w : NATURAL := 14 -- data with of input data vectors + ); + PORT ( + clk : IN STD_LOGIC := '0'; + rst : IN STD_LOGIC; + in_sosi : IN t_dp_sosi := c_dp_sosi_init; -- input data + in_ds : IN NATURAL; -- amount of internal overflow this output + in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); -- bsn corresponding to the data at in_data[in_of] + out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- output data + out_ready : OUT STD_LOGIC + ); +END ddrctrl_output; + + +ARCHITECTURE str OF ddrctrl_output IS + + -- constant for readability + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data with for ddrctrl_repack 168 + + -- signals for connecting the components + SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; + +BEGIN + + -- makes one data vector out of all the data from the t_dp_sosi_arr + u_ddrctrl_output_unpack : ENTITY work.ddrctrl_output_unpack + GENERIC MAP( + g_tech_ddr => g_tech_ddr, + g_in_data_w => g_in_data_w, + g_out_data_w => c_out_data_w + ) + PORT MAP( + clk => clk, + rst => rst, + in_sosi => in_sosi, -- input data + in_ds => in_ds, + in_bsn => in_bsn, + out_sosi => sosi, -- output data + out_ready => out_ready + ); + + -- resizes the input data vector so that the output data vector can be stored into the ddr memory + u_ddrctrl_output_repack : ENTITY work.ddrctrl_output_repack + GENERIC MAP( + g_nof_streams => g_nof_streams, + g_data_w => g_data_w + ) + PORT MAP( + in_sosi => sosi, + out_sosi_arr => out_sosi_arr + ); + +END str; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd new file mode 100644 index 0000000000..2fe5ca5162 --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_repack.vhd @@ -0,0 +1,58 @@ +------------------------------------------------------------------------------- +-- +-- 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: Resize the input data vector so that the output data vector can be +-- stored into the ddr memory. +-- +-- Description: +-- The input data gets resized and put into the output data vector. +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding +-- The output vector must be larger than the input vector. + +LIBRARY IEEE, dp_lib, common_lib; +USE IEEE.std_logic_1164.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY ddrctrl_output_repack IS + GENERIC ( + g_nof_streams : POSITIVE := 12; + g_data_w : NATURAL := 14 + ); + PORT ( + in_sosi : IN t_dp_sosi := c_dp_sosi_init; + out_sosi_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init) + ); +END ddrctrl_output_repack; + +ARCHITECTURE rtl OF ddrctrl_output_repack IS + +BEGIN + + -- putting the data from the stream into different streams. + gen_repack_data : FOR I IN 0 TO g_nof_streams-1 GENERATE + out_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= in_sosi.data(g_data_w*(I+1)-1 DOWNTO g_data_w*I); + out_sosi_arr(I).bsn(c_dp_stream_bsn_w-1 DOWNTO 0) <= in_sosi.bsn(c_dp_stream_bsn_w-1 DOWNTO 0); + END GENERATE; + +END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd new file mode 100644 index 0000000000..a7c644d2ac --- /dev/null +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_output_unpack.vhd @@ -0,0 +1,173 @@ +------------------------------------------------------------------------------- +-- +-- 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: Resize the input data vector so that the output data vector can be +-- stored into the ddr memory. +-- +-- Description: +-- The input data gets resized and put into the output data vector. +-- +-- Remark: +-- Use VHDL coding template from: +-- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding +-- The output vector must be larger than the input vector. + +LIBRARY IEEE, dp_lib, tech_ddr_lib, common_lib; +USE IEEE.std_logic_1164.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE tech_ddr_lib.tech_ddr_pkg.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY ddrctrl_output_unpack IS + GENERIC ( + g_tech_ddr : t_c_tech_ddr; + g_in_data_w : NATURAL; + g_out_data_w : NATURAL + ); + PORT ( + clk : IN STD_LOGIC; + rst : IN STD_LOGIC; + in_sosi : IN t_dp_sosi := c_dp_sosi_init; + in_ds : IN NATURAL; + in_bsn : IN STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + out_sosi : OUT t_dp_sosi := c_dp_sosi_init; + out_ready : OUT STD_LOGIC := '0' + ); +END ddrctrl_output_unpack; + + +ARCHITECTURE rtl OF ddrctrl_output_unpack IS + + -- type for statemachine + TYPE t_state IS ( READING, FH_READ, SH_READ, RESET, IDLE); + + -- record for readability + TYPE t_reg IS RECORD + state : t_state; + a_of : NATURAL; + op_data_cnt : NATURAL; + out_sosi : t_dp_sosi; + out_ready : STD_LOGIC; + END RECORD; + + CONSTANT c_t_reg_init : t_reg := (RESET, 0, 0, c_dp_sosi_init, '0'); + + + -- signals for readability + SIGNAL d_reg : t_reg := c_t_reg_init; + SIGNAL q_reg : t_reg := c_t_reg_init; + +BEGIN + + q_reg <= d_reg WHEN rising_edge(clk); + + -- put the input data into c_v and fill the output vector from c_v + p_state : PROCESS(q_reg, rst, in_sosi, in_ds, in_bsn) + + VARIABLE v : t_reg; + + BEGIN + + v := q_reg; + + CASE q_reg.state IS + WHEN READING => + v.out_sosi.data(g_out_data_w-1 DOWNTO 0) := in_sosi.data((g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); + v.out_sosi.valid := '1'; + v.out_sosi.bsn := ADD_UVEC(q_reg.out_sosi.bsn, "0001", c_dp_stream_bsn_w); + v.op_data_cnt := q_reg.op_data_cnt+1; + + IF rst = '1' THEN + v.state := RESET; + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + v.state := FH_READ; + ELSIF in_sosi.valid = '1' THEN + v.state := READING; + ELSE + v.state := IDLE; + END IF; + + WHEN FH_READ => + v.a_of := (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of-g_in_data_w; + v.out_sosi.data(g_out_data_w-v.a_of-1 DOWNTO 0) := in_sosi.data(g_in_data_w-1 DOWNTO (g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of); + v.out_sosi.valid := '0'; + v.op_data_cnt := 0; + v.out_ready := '1'; + + IF rst = '1' THEN + v.state := RESET; + ELSE + v.state := SH_READ; + END IF; + + WHEN SH_READ => + v.out_sosi.data(g_out_data_w-1 DOWNTO g_out_data_w-q_reg.a_of) := in_sosi.data((g_out_data_w*q_reg.op_data_cnt)+q_reg.a_of-1 DOWNTO 0); + v.out_sosi.valid := '1'; + v.out_sosi.bsn := ADD_UVEC(q_reg.out_sosi.bsn, "0001", c_dp_stream_bsn_w); + v.op_data_cnt := 0; + v.out_ready := '0'; + + IF rst = '1' THEN + v.state := RESET; + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(v.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + v.state := FH_read; + ELSIF in_sosi.valid = '1' THEN + v.state := READING; + ELSE + v.state := IDLE; + END IF; + + WHEN RESET => + v := c_t_reg_init; + + IF rst = '1' THEN + v.state := RESET; + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + v.state := FH_read; + ELSIF in_sosi.valid = '1' THEN + v.state := READING; + ELSE + v.state := IDLE; + END IF; + + WHEN IDLE => + v.out_ready := '1'; + IF rst = '1' THEN + v.state := RESET; + ELSIF in_sosi.valid = '1' AND (g_out_data_w*(q_reg.op_data_cnt+1))+q_reg.a_of > g_in_data_w THEN + v.state := FH_read; + ELSIF in_sosi.valid = '1' THEN + v.state := READING; + v.a_of := in_ds; + ELSE + v.state := IDLE; + END IF; + + END CASE; + + d_reg <= v; + END PROCESS; + + -- fill outputs + out_sosi <= q_reg.out_sosi; + out_ready <= q_reg.out_ready; + + +END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index 6aef30ec40..29deea7061 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -96,6 +96,7 @@ ARCHITECTURE tb OF tb_ddrctrl IS SIGNAL wr_not_rd : STD_LOGIC; SIGNAL stop_in : STD_LOGIC := '0'; SIGNAL bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- testbench signal SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off @@ -201,6 +202,7 @@ BEGIN in_sosi_arr => in_sosi_arr, wr_not_rd => wr_not_rd, stop_in => stop_in, + out_sosi_arr => out_sosi_arr, --PHY phy3_io => phy3_io, -- GitLab