diff --git a/libraries/base/reorder/src/vhdl/reorder_sequencer.vhd b/libraries/base/reorder/src/vhdl/reorder_sequencer.vhd new file mode 100644 index 0000000000000000000000000000000000000000..bc8797401994bb0eb35193a0f504e832600d3eca --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_sequencer.vhd @@ -0,0 +1,251 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- 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 +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- + +LIBRARY IEEE, common_lib, diag_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE work.ddr3_pkg.ALL; + +ENTITY ddr3_seq IS + GENERIC ( + g_ddr3_seq : t_ddr3_seq := c_ddr3_seq; + g_ddr : t_c_ddr3_phy + ); + PORT ( + -- Clocks and reset + dp_rst : IN STD_LOGIC; -- reset synchronous with st_clk + dp_clk : IN STD_LOGIC; -- other clock domain clock + + en_evt : OUT STD_LOGIC; + wr_not_rd : OUT STD_LOGIC; + + start_addr : OUT t_ddr3_addr; + end_addr : OUT t_ddr3_addr; + + done : IN STD_LOGIC; + init_done : IN STD_LOGIC; + ctlr_rdy : IN STD_LOGIC; + + sync_ok_in : IN STD_LOGIC; + sync_ok_out : OUT STD_LOGIC + ); +END ddr3_seq; + + +ARCHITECTURE rtl OF ddr3_seq IS + + CONSTANT c_blocksize : POSITIVE := g_ddr3_seq.wr_nof_chunks * (g_ddr3_seq.wr_chunksize + g_ddr3_seq.gapsize); + CONSTANT c_page_size : POSITIVE := c_blocksize * g_ddr3_seq.nof_blocks; + CONSTANT c_nof_wr_access : POSITIVE := g_ddr3_seq.wr_nof_chunks * g_ddr3_seq.nof_blocks; + CONSTANT c_address_w : POSITIVE := sel_a_b(ceil_log2(2*c_page_size) > g_ddr.a_col_w, ceil_log2(2*c_page_size), g_ddr.a_col_w); + + TYPE state_type is (s_idle, s_write, s_first_write, s_wait_wr, s_read, s_wait_rd); + + TYPE reg_type IS RECORD + rd_page_offset : NATURAL; + wr_page_offset : NATURAL; + ddr3_en : STD_LOGIC; + wr_not_rd : STD_LOGIC; + rd_block_offset : NATURAL; + rd_chunks_offset : NATURAL; + rd_block_cnt : NATURAL; + rd_chunks_cnt : NATURAL; + wr_block_offset : NATURAL; + wr_chunks_offset : NATURAL; + wr_block_cnt : NATURAL; + wr_chunks_cnt : NATURAL; + switch_cnt : NATURAL; -- Counter that counts the write and read accesses to determine the switch between read and write phase. + page_cnt : NATURAL; -- Counter that counts the number of write accesses to determuine the page-swap. + first_write : STD_LOGIC; + sync_ok_out : STD_LOGIC; + start_addr : STD_LOGIC_VECTOR(c_address_w - 1 DOWNTO 0); + end_addr : STD_LOGIC_VECTOR(c_address_w - 1 DOWNTO 0); + state : state_type; -- The state machine. + END RECORD; + + SIGNAL r, rin : reg_type; + +BEGIN + + --------------------------------------------------------------- + -- CHECK IF PROVIDED GENERICS ARE ALLOWED. + --------------------------------------------------------------- + ASSERT NOT((g_ddr3_seq.wr_nof_chunks*g_ddr3_seq.wr_chunksize) /= (g_ddr3_seq.rd_nof_chunks*g_ddr3_seq.rd_chunksize) AND rising_edge(dp_clk)) REPORT "Total write configuration is different from total read configuration!!!" SEVERITY FAILURE; + + p_comb : PROCESS(r, dp_rst, init_done, done, ctlr_rdy, sync_ok_in) + VARIABLE v : reg_type; + BEGIN + + v := r; + v.ddr3_en := '0'; + + CASE r.state IS + WHEN s_idle => + IF(init_done = '1' AND sync_ok_in = '1') THEN + v.first_write := '1'; + v.sync_ok_out := sync_ok_in; + v.state := s_first_write; + END IF; + + WHEN s_first_write => + v.wr_not_rd := '1'; + v.ddr3_en := '1'; + v.start_addr := TO_UVEC(r.wr_page_offset + r.wr_block_offset + r.wr_chunks_offset, c_address_w); + v.end_addr := TO_UVEC(r.wr_page_offset + r.wr_block_offset + r.wr_chunks_offset + g_ddr3_seq.wr_chunksize-4, c_address_w); + v.switch_cnt := r.switch_cnt + 1; + v.state := s_wait_wr; + + WHEN s_write => + IF(done = '1' AND ctlr_rdy = '1') THEN + v.wr_not_rd := '1'; + IF(sync_ok_in = '1') THEN -- Only write when good sync pattern on the input. + v.ddr3_en := '1'; + END IF; + v.start_addr := TO_UVEC(r.wr_page_offset + r.wr_block_offset + r.wr_chunks_offset, c_address_w); + v.end_addr := TO_UVEC(r.wr_page_offset + r.wr_block_offset + r.wr_chunks_offset + g_ddr3_seq.wr_chunksize-4, c_address_w); + v.switch_cnt := r.switch_cnt + 1; + v.state := s_wait_wr; + END IF; + + WHEN s_wait_wr => + v.page_cnt := r.page_cnt + 1; + IF(r.wr_block_cnt = g_ddr3_seq.nof_blocks-1 AND r.wr_chunks_cnt = g_ddr3_seq.wr_nof_chunks-1) THEN + v.wr_block_offset := 0; + v.wr_chunks_offset := 0; + v.wr_block_cnt := 0; + v.wr_chunks_cnt := 0; + ELSIF(r.wr_block_cnt = g_ddr3_seq.nof_blocks-1) THEN + v.wr_block_offset := 0; + v.wr_chunks_offset := r.wr_chunks_offset + g_ddr3_seq.wr_chunksize; + v.wr_block_cnt := 0; + v.wr_chunks_cnt := r.wr_chunks_cnt + 1; + ELSE + v.wr_block_offset := r.wr_block_offset + c_blocksize; + v.wr_block_cnt := r.wr_block_cnt + 1; + END IF; + + IF(r.switch_cnt = g_ddr3_seq.wr_nof_chunks) THEN + v.switch_cnt := 0; + v.state := s_read; + ELSE + v.state := s_write; + END IF; + + WHEN s_read => + IF(done = '1' AND ctlr_rdy = '1') THEN + v.wr_not_rd := '0'; + IF( r.first_write = '0') THEN + v.ddr3_en := '1'; + END IF; + v.start_addr := TO_UVEC(r.rd_page_offset + r.rd_block_offset + r.rd_chunks_offset, c_address_w); + v.end_addr := TO_UVEC(r.rd_page_offset + r.rd_block_offset + r.rd_chunks_offset + g_ddr3_seq.rd_chunksize-4, c_address_w); + v.switch_cnt := r.switch_cnt + 1; + v.state := s_wait_rd; + v.sync_ok_out := sync_ok_in; + END IF; + + WHEN s_wait_rd => + IF(r.switch_cnt = g_ddr3_seq.rd_nof_chunks) THEN + v.switch_cnt := 0; + v.state := s_write; + ELSE + v.state := s_read; + END IF; + + IF(r.rd_block_cnt = g_ddr3_seq.nof_blocks-1 AND r.rd_chunks_cnt = g_ddr3_seq.rd_nof_chunks-1) THEN + v.rd_block_offset := 0; + v.rd_chunks_offset := 0; + v.rd_block_cnt := 0; + v.rd_chunks_cnt := 0; + IF(r.page_cnt = c_nof_wr_access) THEN + v.rd_page_offset := r.wr_page_offset; + v.wr_page_offset := r.rd_page_offset; + v.page_cnt := 0; + v.first_write := '0'; + IF(sync_ok_in = '0') THEN + v.state := s_idle; + END IF; + END IF; + ELSIF(r.rd_block_cnt = g_ddr3_seq.nof_blocks-1) THEN + v.rd_block_offset := 0; + v.rd_chunks_offset := r.rd_chunks_offset + g_ddr3_seq.rd_chunksize; + v.rd_block_cnt := 0; + v.rd_chunks_cnt := r.rd_chunks_cnt + 1; + ELSE + v.rd_block_offset := r.rd_block_offset + c_blocksize; + v.rd_block_cnt := r.rd_block_cnt + 1; + END IF; + + WHEN OTHERS => + v.state := s_idle; + + END CASE; + + IF(dp_rst = '1') THEN + v.rd_page_offset := c_page_size; + v.wr_page_offset := 0; + v.page_cnt := 0; + v.switch_cnt := 0; + v.ddr3_en := '0'; + v.wr_not_rd := '0'; + v.wr_block_offset := 0; + v.wr_chunks_offset := 0; + v.wr_block_cnt := 0; + v.wr_chunks_cnt := 0; + v.rd_block_offset := 0; + v.rd_chunks_offset := 0; + v.rd_block_cnt := 0; + v.rd_chunks_cnt := 0; + v.sync_ok_out := '0'; + v.start_addr := (OTHERS => '0'); + v.end_addr := (OTHERS => '0'); + v.first_write := '1'; + v.state := s_idle; + END IF; + + rin <= v; + + END PROCESS; + + p_regs : PROCESS(dp_clk) + BEGIN + IF RISING_EDGE(dp_clk) THEN + r <= rin; + END IF; + END PROCESS; + + en_evt <= r.ddr3_en; + wr_not_rd <= r.wr_not_rd; + sync_ok_out <= r.sync_ok_out; + + address : PROCESS(r) + BEGIN + start_addr <= c_ddr3_addr_lo; + end_addr <= c_ddr3_addr_lo; + start_addr.column <= r.start_addr(c_ddr3_phy.a_col_w-1 DOWNTO 0); + end_addr.column <= r.end_addr(c_ddr3_phy.a_col_w-1 DOWNTO 0); + start_addr.row(c_address_w-c_ddr3_phy.a_col_w-1 DOWNTO 0) <= r.start_addr(c_address_w-1 DOWNTO c_ddr3_phy.a_col_w); + end_addr.row(c_address_w-c_ddr3_phy.a_col_w-1 DOWNTO 0) <= r.end_addr(c_address_w-1 DOWNTO c_ddr3_phy.a_col_w); + END PROCESS; + +END rtl; + diff --git a/libraries/base/reorder/src/vhdl/reorder_transpose.vhd b/libraries/base/reorder/src/vhdl/reorder_transpose.vhd new file mode 100644 index 0000000000000000000000000000000000000000..ec3b2f046846d281d6bc261c0a94ca924105d436 --- /dev/null +++ b/libraries/base/reorder/src/vhdl/reorder_transpose.vhd @@ -0,0 +1,422 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- 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 +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib, dp_lib, ss_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE work.ddr3_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; + +ENTITY ddr3_transpose IS + GENERIC( + g_sim : BOOLEAN := FALSE; + g_nof_streams : NATURAL := 4; + g_in_dat_w : NATURAL := 8; + g_frame_size_in : NATURAL := 256; + g_frame_size_out : NATURAL := 256; + g_nof_blk_per_sync : NATURAL := 16; + g_use_complex : BOOLEAN := TRUE; + g_ena_pre_transp : BOOLEAN := TRUE; + g_phy : NATURAL := 1; -- 0: ALTMEMPHY 1: UNIPHY_MASTER 2: UNIPHY_SLAVE + g_mts : NATURAL := 800; -- Megatransfers per second + g_ddr3_seq : t_ddr3_seq := c_ddr3_seq; + g_select_file : STRING := "UNUSED" + ); + PORT ( + mm_rst : IN STD_LOGIC; -- reset synchronous with mm_clk + mm_clk : IN STD_LOGIC; -- memory-mapped bus clock + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + -- ST sinks + snk_out_arr : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + -- ST source + src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0); + src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); + + -- Memory Mapped + ram_ss_ss_transp_mosi : IN t_mem_mosi; -- channel select control + ram_ss_ss_transp_miso : OUT t_mem_miso; + + ser_term_ctrl_out : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); + par_term_ctrl_out : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); + + ser_term_ctrl_in : IN STD_LOGIC_VECTOR(13 DOWNTO 0) := (OTHERS => '0'); + par_term_ctrl_in : IN STD_LOGIC_VECTOR(13 DOWNTO 0) := (OTHERS => '0'); + + phy_in : IN t_ddr3_phy_in; + phy_io : INOUT t_ddr3_phy_io; + phy_ou : OUT t_ddr3_phy_ou + ); https://kickass.so/the-tracker-2002-x264-aac-t5162938.html +END ddr3_transpose; + + +ARCHITECTURE str OF ddr3_transpose IS + + CONSTANT c_min_fifo_size : POSITIVE := 256; + CONSTANT c_blocksize : POSITIVE := g_ddr3_seq.wr_nof_chunks * g_ddr3_seq.wr_chunksize; + CONSTANT c_wr_fifo_depth : NATURAL := sel_a_b(c_blocksize > c_min_fifo_size, c_blocksize, c_min_fifo_size);--c_blocksize * 2; + CONSTANT c_rd_fifo_depth : NATURAL := sel_a_b(c_blocksize > c_min_fifo_size, c_blocksize, c_min_fifo_size);--c_blocksize * 2; + + CONSTANT c_total_data_w : NATURAL := g_nof_streams*g_in_dat_w; + CONSTANT c_complex_data_w : NATURAL := c_total_data_w*c_nof_complex; + CONSTANT c_data_w : NATURAL := sel_a_b(g_use_complex, c_complex_data_w, c_total_data_w); + + CONSTANT c_nof_ch_in : NATURAL := g_frame_size_in*g_ddr3_seq.rd_chunksize; + CONSTANT c_nof_ch_sel : NATURAL := c_nof_ch_in; + + CONSTANT c_cnt_sop_w : NATURAL := ceil_log2(g_nof_blk_per_sync)+1; + + SIGNAL ss_in_sosi : t_dp_sosi; + SIGNAL ss_in_siso : t_dp_siso; + + -- ctrl & status DDR3 driver + SIGNAL dvr_start_addr : t_ddr3_addr; + SIGNAL dvr_end_addr : t_ddr3_addr; + + SIGNAL dvr_en : STD_LOGIC; + SIGNAL dvr_wr_not_rd : STD_LOGIC; + SIGNAL dvr_done : STD_LOGIC; + + SIGNAL flush_ena : STD_LOGIC; + + -- DDR3 controller status + SIGNAL ctlr_init_done : STD_LOGIC; + SIGNAL ctlr_rdy : STD_LOGIC; + SIGNAL init_done_data_start : STD_LOGIC; + + SIGNAL transpose_in_sosi : t_dp_sosi; + SIGNAL transpose_in_siso : t_dp_siso; + + SIGNAL transpose_out_sosi : t_dp_sosi; + + SIGNAL block_gen_out_sosi : t_dp_sosi; + SIGNAL pipeline_out_sosi : t_dp_sosi; + + SIGNAL sync_bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + SIGNAL wr_req : STD_LOGIC; + SIGNAL rd_req_i : STD_LOGIC; + SIGNAL rd_dat_i : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0); + SIGNAL rd_val_i : STD_LOGIC; + + SIGNAL cnt_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0); + SIGNAL nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0); + SIGNAL i_mon_nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0); + SIGNAL nxt_mon_nof_sop : STD_LOGIC_VECTOR(c_cnt_sop_w-1 DOWNTO 0); + SIGNAL sync_ok_in : STD_LOGIC; + SIGNAL sync_ok_out : STD_LOGIC; + +BEGIN + + g_merge_in_complex : IF g_use_complex = TRUE GENERATE + PROCESS(snk_in_arr) + BEGIN + ss_in_sosi <= snk_in_arr(0); + FOR i IN 0 TO g_nof_streams-1 LOOP + ss_in_sosi.data((2*i+1)*g_in_dat_w-1 DOWNTO 2*i*g_in_dat_w) <= snk_in_arr(i).re(g_in_dat_w-1 DOWNTO 0); + ss_in_sosi.data((2*i+2)*g_in_dat_w-1 DOWNTO (2*i+1)*g_in_dat_w) <= snk_in_arr(i).im(g_in_dat_w-1 DOWNTO 0); + END LOOP; + END PROCESS; + END GENERATE; + +-- g_merge_in_data : IF g_use_complex = FALSE GENERATE +-- merge_input : PROCESS(snk_in_arr) +-- BEGIN +-- transpose_in_sosi <= snk_in_arr(0); +-- FOR i IN 0 TO g_nof_streams-1 LOOP +-- transpose_in_sosi.data((i+1)*g_in_dat_w-1 DOWNTO i*g_in_dat_w) <= snk_in_arr(i).data(g_in_dat_w-1 DOWNTO 0); +-- END LOOP; +-- END PROCESS; +-- END GENERATE; + + gen_pre_transpose : IF g_ena_pre_transp = TRUE GENERATE + u_single_ss : ENTITY ss_lib.ss + GENERIC MAP ( + g_dsp_data_w => c_total_data_w, + g_nof_ch_in => c_nof_ch_in, + g_nof_ch_sel => c_nof_ch_sel, + g_select_file_name => g_select_file, + g_use_complex => FALSE + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + + -- Memory Mapped + ram_ss_ss_mosi => ram_ss_ss_transp_mosi, + ram_ss_ss_miso => ram_ss_ss_transp_miso, + + -- Streaming + input_sosi => ss_in_sosi, + input_siso => ss_in_siso, + + output_sosi => transpose_in_sosi, + output_siso => transpose_in_siso + ); + END GENERATE; + + gen_not_pre_transpose : IF g_ena_pre_transp = FALSE GENERATE + transpose_in_sosi <= ss_in_sosi; + ss_in_siso <= transpose_in_siso; + END GENERATE; + + g_siso : FOR J IN 0 TO g_nof_streams-1 GENERATE + snk_out_arr(J) <= ss_in_siso; + END GENERATE; + + u_ddr3: ENTITY work.ddr3 + GENERIC MAP( + g_ddr => c_ddr3_phy_4g, + g_phy => g_phy, + g_mts => g_mts, + g_wr_data_w => c_data_w, + g_wr_use_ctrl => TRUE, + g_wr_fifo_depth => c_wr_fifo_depth, + g_rd_fifo_depth => c_rd_fifo_depth, + g_rd_data_w => c_data_w, + g_flush_wr_fifo => TRUE, + g_flush_ext_ena => TRUE, + g_flush_sop => TRUE, + g_flush_sop_sync => TRUE, + g_flush_sop_channel => FALSE, + g_flush_sop_start_channel => 0, + g_flush_nof_channels => 0 + ) + PORT MAP ( + ctlr_ref_clk => dp_clk, + ctlr_rst => dp_rst, + + phy_in => phy_in, + phy_io => phy_io, + phy_ou => phy_ou, + + ctlr_gen_clk => OPEN, + ctlr_gen_rst => OPEN, + + ctlr_init_done => ctlr_init_done, + + ctlr_rdy => ctlr_rdy, + dvr_start_addr => dvr_start_addr, + dvr_end_addr => dvr_end_addr, + + dvr_done => dvr_done, + dvr_wr_not_rd => dvr_wr_not_rd, + dvr_en => dvr_en, + + wr_clk => dp_clk, + wr_rst => dp_rst, + + wr_sosi => transpose_in_sosi, + wr_siso => transpose_in_siso, + + flush_ena => flush_ena, + + rd_sosi => transpose_out_sosi, + rd_siso => src_in_arr(0), + + rd_clk => dp_clk, + rd_rst => dp_rst, + + ser_term_ctrl_out => ser_term_ctrl_out, + par_term_ctrl_out => par_term_ctrl_out, + + ser_term_ctrl_in => ser_term_ctrl_in, + par_term_ctrl_in => par_term_ctrl_in, + + rd_fifo_usedw => OPEN + ); + + flush_ena <= NOT(ctlr_init_done) OR NOT(sync_ok_out); + init_done_data_start <= ctlr_init_done AND transpose_in_sosi.sync; + + u_ddr3_sequencer: ENTITY work.ddr3_seq + GENERIC MAP( + g_ddr => c_ddr3_phy_4g, + g_ddr3_seq => g_ddr3_seq + ) + PORT MAP ( + dp_rst => dp_rst, + dp_clk => dp_clk, + + en_evt => dvr_en, + wr_not_rd => dvr_wr_not_rd, + + start_addr => dvr_start_addr, + end_addr => dvr_end_addr, + + done => dvr_done, + init_done => init_done_data_start, + ctlr_rdy => ctlr_rdy, + + sync_ok_in => sync_ok_in, + sync_ok_out => sync_ok_out + ); + + u_cnt_sop : ENTITY common_lib.common_counter + GENERIC MAP ( + g_width => c_cnt_sop_w + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + cnt_clr => transpose_in_sosi.sync, + cnt_en => transpose_in_sosi.sop, + count => cnt_sop + ); + + nof_sop <= INCR_UVEC(cnt_sop, 1); -- +1 because the sop at the sync also counts + nxt_mon_nof_sop <= nof_sop WHEN transpose_in_sosi.sync='1' ELSE i_mon_nof_sop; + sync_ok_in <= '1' WHEN TO_UINT(i_mon_nof_sop) = g_nof_blk_per_sync AND TO_UINT(nof_sop) <= g_nof_blk_per_sync ELSE '0'; + + p_clk : PROCESS(dp_rst, dp_clk) + BEGIN + IF dp_rst = '1' THEN + i_mon_nof_sop <= (OTHERS=>'0'); + ELSIF rising_edge(dp_clk) THEN + i_mon_nof_sop <= nxt_mon_nof_sop; + END IF; + END PROCESS; + + --------------------------------------------------------------- + -- FIFO FOR SYNC-BSN + --------------------------------------------------------------- + wr_req <= snk_in_arr(0).sync AND ctlr_init_done; + + u_sync_bsn_fifo : ENTITY common_lib.common_fifo_sc + GENERIC MAP ( + g_use_lut => TRUE, -- Make this FIFO in logic, since it's only 2 words deep. + g_reset => FALSE, + g_init => FALSE, + g_dat_w => c_dp_stream_bsn_w, + g_nof_words => 16 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + wr_dat => snk_in_arr(0).bsn, + wr_req => wr_req, + wr_ful => OPEN , + rd_dat => rd_dat_i, + rd_req => rd_req_i, + rd_emp => open, + rd_val => rd_val_i, + usedw => OPEN + ); + + --------------------------------------------------------------- + -- CREATE READ-AHEAD FIFO INTERFACE FOR SYNC-BSN + --------------------------------------------------------------- + u_fifo_adapter : ENTITY common_lib.common_fifo_rd + GENERIC MAP ( + g_dat_w => c_dp_stream_bsn_w + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + -- ST sink: RL = 1 + fifo_req => rd_req_i, + fifo_dat => rd_dat_i, + fifo_val => rd_val_i, + -- ST source: RL = 0 + rd_req => block_gen_out_sosi.sync, + rd_dat => sync_bsn, + rd_val => OPEN + ); + + ----------------------- + -- Pipeline + ----------------------- + u_dp_pipeline : ENTITY dp_lib.dp_pipeline + GENERIC MAP( + g_pipeline => 1 + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + -- ST sink + snk_out => OPEN, + snk_in => transpose_out_sosi, + -- ST source + src_in => OPEN, + src_out => pipeline_out_sosi + ); + + -------------------- + -- DP BLOCK GEN (providing sop/eop) + -------------------- + u_dp_block_gen : ENTITY dp_lib.dp_block_gen + GENERIC MAP( + g_use_src_in => FALSE, + g_nof_data => g_frame_size_out, + g_nof_blk_per_sync => g_nof_blk_per_sync, + g_empty => 0, + g_channel => 0, + g_error => 0 + ) + PORT MAP( + rst => dp_rst, + clk => dp_clk, + snk_in => transpose_out_sosi, + + -- Use incoming data to generate more data + src_in => c_dp_siso_rdy, + src_out => block_gen_out_sosi, + en => '1' + ); + + g_merge_out_complex : IF g_use_complex = TRUE GENERATE + gen_merge_out : PROCESS(block_gen_out_sosi, pipeline_out_sosi) + BEGIN + FOR i IN 0 TO g_nof_streams-1 LOOP + src_out_arr(i) <= block_gen_out_sosi; + src_out_arr(i).valid <= pipeline_out_sosi.valid; + src_out_arr(i).re <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2*i+1)*g_in_dat_w-1 DOWNTO 2*i*g_in_dat_w)); + src_out_arr(i).im <= RESIZE_DP_DSP_DATA(pipeline_out_sosi.data((2*i+2)*g_in_dat_w-1 DOWNTO (2*i+1)*g_in_dat_w)); + IF (block_gen_out_sosi.sync = '1') THEN + src_out_arr(i).bsn <= sync_bsn; + END IF; + END LOOP; + END PROCESS; + END GENERATE; + + g_merge_out_data : IF g_use_complex = FALSE GENERATE + gen_merge_out : PROCESS(block_gen_out_sosi, pipeline_out_sosi) + BEGIN + FOR i IN 0 TO g_nof_streams-1 LOOP + src_out_arr(i) <= block_gen_out_sosi; + src_out_arr(i).valid <= pipeline_out_sosi.valid; + src_out_arr(i).data <= RESIZE_DP_DATA(pipeline_out_sosi.data((i+1)*g_in_dat_w-1 DOWNTO i*g_in_dat_w)); + IF (block_gen_out_sosi.sync = '1') THEN + src_out_arr(i).bsn <= sync_bsn; + END IF; + END LOOP; + END PROCESS; + END GENERATE; + +END str; + + diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd new file mode 100644 index 0000000000000000000000000000000000000000..206a08c9206af270a24d1145da84b8e851ae862c --- /dev/null +++ b/libraries/base/reorder/tb/vhdl/tb_reorder_transpose.vhd @@ -0,0 +1,417 @@ + +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2012 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- 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 +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +------------------------------------------------------------------------------- +-- +-- Purpose: Testbench for the ddr3_transpose unit +-- To be used in conjunction with python testscript: ../python/tc_transpose_ddr3.py +-- +-- +-- Usage: +-- > as 8 +-- > run -all +-- > run python script in separate terminal: "python tc_transpose_ddr3.py --unb 0 --fn 0 --sim" +-- > Stop the simulation manually in Modelsim by pressing the stop-button. +-- > Evalute the WAVE window. + +LIBRARY IEEE, common_lib, mm_lib, diag_lib, dp_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE mm_lib.mm_file_unb_pkg.ALL; +USE mm_lib.mm_file_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE diag_lib.diag_pkg.ALL; +USE work.ddr3_pkg.ALL; + +ENTITY tb_ddr3_transpose IS + GENERIC ( + g_wr_chunksize : POSITIVE := 64; + g_wr_nof_chunks : POSITIVE := 1; + g_rd_chunksize : POSITIVE := 16; + g_rd_nof_chunks : POSITIVE := 4; + g_gapsize : NATURAL := 0; + g_nof_blocks : POSITIVE := 4; + g_nof_blk_per_sync : POSITIVE := 64 + ); +END tb_ddr3_transpose; + +ARCHITECTURE tb OF tb_ddr3_transpose IS + + CONSTANT c_sim : BOOLEAN := TRUE; + + ---------------------------------------------------------------------------- + -- Clocks and resets + ---------------------------------------------------------------------------- + CONSTANT c_mm_clk_period : TIME := 100 ps; + CONSTANT c_dp_clk_period : TIME := 5 ns; + CONSTANT c_dp_pps_period : NATURAL := 64; + + SIGNAL dp_pps : STD_LOGIC; + + SIGNAL mm_rst : STD_LOGIC := '1'; + SIGNAL mm_clk : STD_LOGIC := '0'; + + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_clk : STD_LOGIC := '0'; + + ---------------------------------------------------------------------------- + -- MM buses + ---------------------------------------------------------------------------- + -- TB + SIGNAL reg_diag_bg_mosi : t_mem_mosi; + SIGNAL reg_diag_bg_miso : t_mem_miso; + + SIGNAL ram_diag_bg_mosi : t_mem_mosi; + SIGNAL ram_diag_bg_miso : t_mem_miso; + + SIGNAL ram_diag_data_buf_re_mosi : t_mem_mosi; + SIGNAL ram_diag_data_buf_re_miso : t_mem_miso; + + SIGNAL reg_diag_data_buf_re_mosi : t_mem_mosi; + SIGNAL reg_diag_data_buf_re_miso : t_mem_miso; + + SIGNAL ram_diag_data_buf_im_mosi : t_mem_mosi; + SIGNAL ram_diag_data_buf_im_miso : t_mem_miso; + + SIGNAL reg_diag_data_buf_im_mosi : t_mem_mosi; + SIGNAL reg_diag_data_buf_im_miso : t_mem_miso; + + -- DUT + SIGNAL ram_ss_ss_transp_mosi : t_mem_mosi := c_mem_mosi_rst; + SIGNAL ram_ss_ss_transp_miso : t_mem_miso := c_mem_miso_rst; + + ---------------------------------------------------------------------------- + -- Component declaration of mm_file + ---------------------------------------------------------------------------- + COMPONENT mm_file + GENERIC( + g_file_prefix : STRING; + g_update_on_change : BOOLEAN := FALSE + ); + PORT ( + mm_rst : IN STD_LOGIC; + mm_clk : IN STD_LOGIC; + mm_master_out : OUT t_mem_mosi; + mm_master_in : IN t_mem_miso + ); + END COMPONENT; + + -- Compose the Constants for the DUT + CONSTANT c_ddr3_seq_conf : t_ddr3_seq := (g_wr_chunksize, + g_wr_nof_chunks, + g_rd_chunksize, + g_rd_nof_chunks, + g_gapsize, + g_nof_blocks); + + CONSTANT c_blocksize : POSITIVE := g_wr_nof_chunks * g_wr_chunksize; + CONSTANT c_page_size : POSITIVE := c_blocksize * g_nof_blocks; + + CONSTANT c_ddr : t_c_ddr3_phy := c_ddr3_phy_4g; + CONSTANT c_mts : NATURAL := 800;--1066; --800 + CONSTANT c_phy : NATURAL := 1; + CONSTANT c_data_w : NATURAL := 64; + + CONSTANT c_ctrl_ref_clk_period : TIME := 5000 ps; + + -- Custom definitions of constants + CONSTANT c_bg_block_len : NATURAL := c_blocksize * g_rd_chunksize; + CONSTANT c_db_block_len : NATURAL := c_blocksize * g_rd_chunksize; + + -- Configuration of the block generator: + CONSTANT c_bg_nof_output_streams : POSITIVE := 4; + CONSTANT c_bg_buf_dat_w : POSITIVE := c_nof_complex*8; + CONSTANT c_bg_buf_adr_w : POSITIVE := ceil_log2(c_bg_block_len); + CONSTANT c_bg_data_file_prefix : STRING := "UNUSED"; -- "../../../src/hex/tb_bg_dat"; + CONSTANT c_bg_data_file_index_arr : t_nat_natural_arr := array_init(0, 128, 1); + + -- Configuration of the databuffers: + CONSTANT c_db_nof_streams : POSITIVE := 4; + CONSTANT c_db_data_w : POSITIVE := c_diag_db_max_data_w; + CONSTANT c_db_buf_nof_data : POSITIVE := c_db_block_len; + CONSTANT c_db_buf_use_sync : BOOLEAN := FALSE; + CONSTANT c_db_data_type_re : t_diag_data_type_enum := e_real; + CONSTANT c_db_data_type_im : t_diag_data_type_enum := e_imag; + + SIGNAL bg_siso_arr : t_dp_siso_arr(c_bg_nof_output_streams -1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + SIGNAL bg_sosi_arr : t_dp_sosi_arr(c_bg_nof_output_streams -1 DOWNTO 0); + + SIGNAL out_sosi_arr : t_dp_sosi_arr(c_bg_nof_output_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL out_siso_arr : t_dp_siso_arr(c_bg_nof_output_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy); + + -- Siganls to connect the memory driver with the mm register interface + SIGNAL ctlr_ref_clk : STD_LOGIC := '0'; + SIGNAL ctlr_rst : STD_LOGIC := '1'; + SIGNAL ctlr_gen_clk : STD_LOGIC; + SIGNAL ctlr_gen_rst : STD_LOGIC; + + SIGNAL ctlr_rdy : STD_LOGIC; + SIGNAL ctlr_init_done : STD_LOGIC; + + SIGNAL dvr_start_addr : t_ddr3_addr; + SIGNAL dvr_end_addr : t_ddr3_addr; + + SIGNAL dvr_en : STD_LOGIC; + SIGNAL dvr_wr_not_rd : STD_LOGIC; + SIGNAL dvr_done : STD_LOGIC; + + + -- Signals to interface with the DDR3 memory model. + SIGNAL phy_in : t_ddr3_phy_in; + SIGNAL phy_io : t_ddr3_phy_io; + SIGNAL phy_ou : t_ddr3_phy_ou; + + SIGNAL ras_n : STD_LOGIC_VECTOR(0 DOWNTO 0); + SIGNAL cas_n : STD_LOGIC_VECTOR(0 DOWNTO 0); + SIGNAL we_n : STD_LOGIC_VECTOR(0 DOWNTO 0); + + +BEGIN + + ---------------------------------------------------------------------------- + -- Clock and reset generation + ---------------------------------------------------------------------------- + mm_clk <= NOT mm_clk AFTER c_mm_clk_period/2; + mm_rst <= '1', '0' AFTER c_mm_clk_period*5; + + dp_clk <= NOT dp_clk AFTER c_dp_clk_period/2; + dp_rst <= '1', '0' AFTER c_dp_clk_period*5; + + ctlr_ref_clk <= NOT ctlr_ref_clk AFTER c_ctrl_ref_clk_period/2; + ctlr_rst <= '1', '0' AFTER c_ctrl_ref_clk_period*5; + + ------------------------------------------------------------------------------ + -- External PPS + ------------------------------------------------------------------------------ + proc_common_gen_pulse(1, c_dp_pps_period, '1', dp_clk, dp_pps); + + ---------------------------------------------------------------------------- + -- Procedure that polls a sim control file that can be used to e.g. get + -- the simulation time in ns + ---------------------------------------------------------------------------- + mmf_poll_sim_ctrl_file(c_mmf_unb_file_path & "sim.ctrl", c_mmf_unb_file_path & "sim.stat"); + + ---------------------------------------------------------------------------- + -- MM buses + ---------------------------------------------------------------------------- + -- TB + u_mm_file_reg_diag_bg : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "REG_DIAG_BG") + PORT MAP(mm_rst, mm_clk, reg_diag_bg_mosi, reg_diag_bg_miso); + + u_mm_file_ram_diag_bg : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "RAM_DIAG_BG") + PORT MAP(mm_rst, mm_clk, ram_diag_bg_mosi, ram_diag_bg_miso); + + u_mm_file_ram_diag_data_buf_re : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "RAM_DIAG_DATA_BUFFER_REAL") + PORT MAP(mm_rst, mm_clk, ram_diag_data_buf_re_mosi, ram_diag_data_buf_re_miso); + + u_mm_file_reg_diag_data_buf_re : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "REG_DIAG_DATA_BUFFER_REAL") + PORT MAP(mm_rst, mm_clk, reg_diag_data_buf_re_mosi, reg_diag_data_buf_re_miso); + + u_mm_file_ram_diag_data_buf_im : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "RAM_DIAG_DATA_BUFFER_IMAG") + PORT MAP(mm_rst, mm_clk, ram_diag_data_buf_im_mosi, ram_diag_data_buf_im_miso); + + u_mm_file_reg_diag_data_buf_im : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "REG_DIAG_DATA_BUFFER_IMAG") + PORT MAP(mm_rst, mm_clk, reg_diag_data_buf_im_mosi, reg_diag_data_buf_im_miso); + + u_mm_file_ram_ss_ss_transp : mm_file GENERIC MAP(mmf_unb_file_prefix(0, 0, "FN") & "RAM_SS_SS_WIDE") + PORT MAP(mm_rst, mm_clk, ram_ss_ss_transp_mosi, ram_ss_ss_transp_miso); + + ---------------------------------------------------------------------------- + -- Source: block generator + ---------------------------------------------------------------------------- + u_bg : ENTITY diag_lib.mms_diag_block_gen + GENERIC MAP( + g_nof_output_streams => c_bg_nof_output_streams, + g_buf_dat_w => c_bg_buf_dat_w, + g_buf_addr_w => c_bg_buf_adr_w, + g_file_index_arr => c_bg_data_file_index_arr, + g_file_name_prefix => c_bg_data_file_prefix + ) + PORT MAP( + -- System + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + en_sync => dp_pps, + -- MM interface + reg_bg_ctrl_mosi => reg_diag_bg_mosi, + reg_bg_ctrl_miso => reg_diag_bg_miso, + ram_bg_data_mosi => ram_diag_bg_mosi, + ram_bg_data_miso => ram_diag_bg_miso, + -- ST interface + out_siso_arr => bg_siso_arr, + out_sosi_arr => bg_sosi_arr + ); + + ---------------------------------------------------------------------------- + -- DUT: Device Under Test + ---------------------------------------------------------------------------- + u_dut: ENTITY work.ddr3_transpose + GENERIC MAP( + g_sim => TRUE, + g_nof_streams => c_bg_nof_output_streams, + g_in_dat_w => c_bg_buf_dat_w/c_nof_complex, + g_frame_size_in => g_wr_chunksize, + g_frame_size_out => g_wr_chunksize, + g_nof_blk_per_sync => g_nof_blk_per_sync, + g_use_complex => TRUE, + g_ena_pre_transp => FALSE, + g_phy => c_phy, + g_mts => c_mts, + g_ddr3_seq => c_ddr3_seq_conf + ) + PORT MAP ( + mm_rst => mm_rst, + mm_clk => mm_clk, + + dp_rst => dp_rst, + dp_clk => dp_clk, + + snk_out_arr => bg_siso_arr, + snk_in_arr => bg_sosi_arr, + -- ST source + src_in_arr => out_siso_arr, + src_out_arr => out_sosi_arr, + + ram_ss_ss_transp_mosi => ram_ss_ss_transp_mosi, + ram_ss_ss_transp_miso => ram_ss_ss_transp_miso, + + ser_term_ctrl_out => OPEN, + par_term_ctrl_out => OPEN, + + ser_term_ctrl_in => OPEN, + par_term_ctrl_in => OPEN, + + phy_in => phy_in, + phy_io => phy_io, + phy_ou => phy_ou + ); + + u_4gb_800_ddr3_model : component alt_mem_if_ddr3_mem_model_top_ddr3_mem_if_dm_pins_en_mem_if_dqsn_en + generic map ( + MEM_IF_ADDR_WIDTH => 15, + MEM_IF_ROW_ADDR_WIDTH => 15, + MEM_IF_COL_ADDR_WIDTH => 10, + MEM_IF_CS_PER_RANK => 1, + MEM_IF_CONTROL_WIDTH => 1, + MEM_IF_DQS_WIDTH => 8, + MEM_IF_CS_WIDTH => 2, + MEM_IF_BANKADDR_WIDTH => 3, + MEM_IF_DQ_WIDTH => 64, + MEM_IF_CK_WIDTH => 2, + MEM_IF_CLK_EN_WIDTH => 2, + DEVICE_WIDTH => 1, + MEM_TRCD => 6, + MEM_TRTP => 3, + MEM_DQS_TO_CLK_CAPTURE_DELAY => 100, + MEM_CLK_TO_DQS_CAPTURE_DELAY => 100000, + MEM_IF_ODT_WIDTH => 2, + MEM_MIRROR_ADDRESSING_DEC => 0, + MEM_REGDIMM_ENABLED => false, + DEVICE_DEPTH => 1, + MEM_GUARANTEED_WRITE_INIT => false, + MEM_VERBOSE => true, + MEM_INIT_EN => false, + MEM_INIT_FILE => "", + DAT_DATA_WIDTH => 32 + ) + port map ( + mem_a => phy_ou.a(c_ddr.a_w-1 DOWNTO 0), + mem_ba => phy_ou.ba, + mem_ck => phy_io.clk, + mem_ck_n => phy_io.clk_n, + mem_cke => phy_ou.cke(c_ddr.cs_w-1 DOWNTO 0), + mem_cs_n => phy_ou.cs_n(c_ddr.cs_w-1 DOWNTO 0), + mem_dm => phy_ou.dm, + mem_ras_n => ras_n, + mem_cas_n => cas_n, + mem_we_n => we_n, + mem_reset_n => phy_ou.reset_n, + mem_dq => phy_io.dq, + mem_dqs => phy_io.dqs, + mem_dqs_n => phy_io.dqs_n, + mem_odt => phy_ou.odt + ); + + ras_n(0) <= phy_ou.ras_n; + cas_n(0) <= phy_ou.cas_n; + we_n(0) <= phy_ou.we_n; + + ---------------------------------------------------------------------------- + -- Sink: data buffer real + ---------------------------------------------------------------------------- + u_data_buf_re : ENTITY diag_lib.mms_diag_data_buffer + GENERIC MAP ( + g_nof_streams => c_db_nof_streams, + g_data_type => c_db_data_type_re, + g_data_w => c_db_data_w, + g_buf_nof_data => c_db_buf_nof_data, + g_buf_use_sync => c_db_buf_use_sync + ) + PORT MAP ( + -- System + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + -- MM interface + ram_data_buf_mosi => ram_diag_data_buf_re_mosi, + ram_data_buf_miso => ram_diag_data_buf_re_miso, + reg_data_buf_mosi => reg_diag_data_buf_re_mosi, + reg_data_buf_miso => reg_diag_data_buf_re_miso, + -- ST interface + in_sync => OPEN, + in_sosi_arr => out_sosi_arr + ); + + ---------------------------------------------------------------------------- + -- Sink: data buffer imag + ---------------------------------------------------------------------------- + u_data_buf_im : ENTITY diag_lib.mms_diag_data_buffer + GENERIC MAP ( + g_nof_streams => c_db_nof_streams, + g_data_type => c_db_data_type_im, + g_data_w => c_db_data_w, + g_buf_nof_data => c_db_buf_nof_data, + g_buf_use_sync => c_db_buf_use_sync + ) + PORT MAP ( + -- System + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + -- MM interface + ram_data_buf_mosi => ram_diag_data_buf_im_mosi, + ram_data_buf_miso => ram_diag_data_buf_im_miso, + reg_data_buf_mosi => reg_diag_data_buf_im_mosi, + reg_data_buf_miso => reg_diag_data_buf_im_miso, + -- ST interface + in_sync => OPEN, + in_sosi_arr => out_sosi_arr + ); + +END tb;