Skip to content
Snippets Groups Projects
Select Git revision
  • 8bf7a5f02dde726957bd82add70619eab49b755c
  • master default protected
  • RTSD-375
  • L2SDP-1134
  • L2SDP-1137
  • L2SDP-LIFT
  • L2SDP-1113
  • HPR-158
8 results

ddr3_transpose.vhd

  • Eric Kooistra's avatar
    Eric Kooistra authored
    Do not assign default value for g_reset in common_fifo_sc. To avoid clutter in report when using e.g.: grep -rl 'g_reset ' libraries.
    ce8b9e85
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ddr3_transpose.vhd 14.29 KiB
    --------------------------------------------------------------------------------
    --
    -- 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, tech_ddr_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 dp_lib.dp_stream_pkg.all;
    use tech_ddr_lib.tech_ddr_pkg.all;
    use work.ddr3_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;
    
        -- MM register map for DDR controller status info
        reg_io_ddr_mosi       : in    t_mem_mosi := c_mem_mosi_rst;
        reg_io_ddr_miso       : out   t_mem_miso;
    
        -- 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_tech_ddr3_phy_in;
        phy_io                : inout t_tech_ddr3_phy_io;
        phy_ou                : out   t_tech_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 (
    
        mm_clk             => mm_clk,
        mm_rst             => mm_rst,
    
        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,
    
        reg_io_ddr_mosi    => reg_io_ddr_mosi,
        reg_io_ddr_miso    => reg_io_ddr_miso,
    
        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_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;