From 95cc27d90e20eed4490265f8858cb28de87d8b12 Mon Sep 17 00:00:00 2001 From: Pepping <pepping> Date: Thu, 2 Apr 2015 12:44:58 +0000 Subject: [PATCH] copy + added ddr_ref_clk en ddr_gen_clk --- libraries/io/ddr3/src/vhdl/ddr3_transpose.vhd | 429 ++++++++++++++++++ 1 file changed, 429 insertions(+) create mode 100644 libraries/io/ddr3/src/vhdl/ddr3_transpose.vhd diff --git a/libraries/io/ddr3/src/vhdl/ddr3_transpose.vhd b/libraries/io/ddr3/src/vhdl/ddr3_transpose.vhd new file mode 100644 index 0000000000..c6bd89c7aa --- /dev/null +++ b/libraries/io/ddr3/src/vhdl/ddr3_transpose.vhd @@ -0,0 +1,429 @@ +-------------------------------------------------------------------------------- +-- +-- 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_ref_clk : IN STD_LOGIC; + dp_ref_rst : IN STD_LOGIC; + + dp_clk : IN STD_LOGIC; + dp_rst : IN STD_LOGIC; + + dp_out_clk : OUT STD_LOGIC; + dp_out_rst : OUT 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 + ); +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_ref_clk, + ctlr_rst => dp_ref_rst, + + phy_in => phy_in, + phy_io => phy_io, + phy_ou => phy_ou, + + ctlr_gen_clk => dp_out_clk, + ctlr_gen_rst => dp_out_rst, + + 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; + + -- GitLab