Skip to content
Snippets Groups Projects
mms_io_ddr_diag.vhd 12.5 KiB
Newer Older
-------------------------------------------------------------------------------
--
-- Copyright (C) 2015
-- 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: Provide streaming access to IO_DDR using a Tx seq and a Rx seq with optional DB RAM
--   The BG Tx seq stream writes the DDR and the read stream is passed on to the DB Rx seq. The BG
--   block generation and BG RAM are not used. The DB RAM can be used for extra read data monitoring.
--   The DDR write and read access is controlled via the driver MM interface of the mms_io_ddr.
--                              DB RAM
--        Tx seq --> IO_DDR --> Rx seq
--           |         |          |
--           |         |          |
--      MM --+---------+----------+--
--
-- Remark:
-- . The ratio of g_dp_data_w and func_tech_ddr_ctlr_data_w(g_io_tech_ddr)must be a power of 2 due to the mixed width FIFO. By
--   using a wider g_dp_data_w the DDR data access rate can be increased to the maximum that is possible for the DDR memory.
--   - For DDR3 with ctrl_data_w = dq_w * rsl = 64 * 4 = 256 choose g_dp_data_w e.g. 16, 32, 64, 128, 256, 512.
--   - For DDR4 with ctrl_data_w = dq_w * rsl = 72 * 8 = 576 choose g_dp_data_w e.g. 18, 36, 72, 144, 288, 576, 1152.
-- . The DB RAM gets refilled with new read data from the DDR after the last word has been read via the MM.
-- . The DB RAM only captures the lowest c_word_w=32 bits of the g_dp_data_w. This fits the MM bus data width
--   and it is sufficient because typically g_dp_seq_dat_w <= c_word_w.
-- . This component could have user write input and user read output. The constraint is that the user DDR access is suitable for:
--   - MM control of the mms_io_ddr to issue a write or a read access.
--   - g_wr_flush_mode="VAL" in the io_ddr, because that the Tx seq source does not use "SOP" or "SYNC"

LIBRARY IEEE, common_lib, dp_lib, diag_lib, technology_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 diag_lib.diag_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE tech_ddr_lib.tech_ddr_pkg.ALL;

ENTITY mms_io_ddr_diag IS
  GENERIC (
Eric Kooistra's avatar
Eric Kooistra committed
    g_sim_model_ddr   : BOOLEAN := FALSE;
    g_technology      : NATURAL := c_tech_select_default;
    g_dp_data_w       : NATURAL := 32;  -- DP data width, func_tech_ddr_ctlr_data_w(g_io_tech_ddr)/g_dp_data_w must be a power of 2 due to the mixed width FIFO
    g_dp_seq_dat_w    : NATURAL := 32;  -- >= 1, test sequence data width. Choose g_dp_seq_dat_w <= g_dp_data_w. The seq data gets replicated to fill g_dp_data_w.
    g_dp_fifo_depth   : NATURAL := 2048;  -- defined at DP side of the FIFOs, write FIFO depth and read FIFO depth
    g_db_use_db       : BOOLEAN := FALSE;
    g_db_buf_nof_data : NATURAL := 1024    -- nof words per data buffer
  );
  PORT (
    ---------------------------------------------------------------------------
    -- System
    ---------------------------------------------------------------------------
    mm_rst              : IN  STD_LOGIC;
    mm_clk              : IN  STD_LOGIC;
    dp_rst              : IN  STD_LOGIC;
    dp_clk              : IN  STD_LOGIC;  -- use alternative external clock or externally connect to ctlr_clk_out
    
    ---------------------------------------------------------------------------
    -- IO_DDR
    ---------------------------------------------------------------------------
    -- DDR reference clock
    ctlr_ref_clk        : IN    STD_LOGIC;
    ctlr_ref_rst        : IN    STD_LOGIC;

    -- DDR controller clock domain
    ctlr_clk_out        : OUT   STD_LOGIC;
    ctlr_rst_out        : OUT   STD_LOGIC;

    ctlr_clk_in         : IN    STD_LOGIC;  -- connect ctlr_clk_out to ctlr_clk_in at top level to avoid potential delta-cycle differences between the same clock
    ctlr_rst_in         : IN    STD_LOGIC;  -- connect ctlr_rst_out to ctlr_rst_in at top level

    -- MM interface
    reg_io_ddr_mosi     : IN    t_mem_mosi := c_mem_mosi_rst;  -- register for DDR controller status info
    reg_io_ddr_miso     : OUT   t_mem_miso;

    -- Write / read FIFO status for monitoring purposes (in dp_clk domain)
    wr_fifo_usedw       : OUT   STD_LOGIC_VECTOR(ceil_log2(g_dp_fifo_depth)-1 DOWNTO 0);
    rd_fifo_usedw       : OUT   STD_LOGIC_VECTOR(ceil_log2(g_dp_fifo_depth)-1 DOWNTO 0);
    -- DDR3 pass on termination control from master to slave controller
    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;

    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    -- MM interface
    reg_tx_seq_mosi  : IN  t_mem_mosi := c_mem_mosi_rst;  -- Tx seq control (one per stream because c_reg_tx_seq_broadcast=FALSE)
    reg_tx_seq_miso  : OUT t_mem_miso;
    ---------------------------------------------------------------------------
    ---------------------------------------------------------------------------
    -- MM interface
    reg_data_buf_mosi : IN  t_mem_mosi := c_mem_mosi_rst;  -- DB control register (one per stream)
    reg_data_buf_miso : OUT t_mem_miso;

    ram_data_buf_mosi : IN  t_mem_mosi := c_mem_mosi_rst;  -- DB buffer RAM (one per streams)
    ram_data_buf_miso : OUT t_mem_miso;

    reg_rx_seq_mosi   : IN  t_mem_mosi := c_mem_mosi_rst;  -- Rx seq control register (one per streams)
  );
END mms_io_ddr_diag;


ARCHITECTURE str OF mms_io_ddr_diag IS

  CONSTANT c_io_wr_fifo_depth      : NATURAL := (g_dp_fifo_depth * g_dp_data_w) / func_tech_ddr_ctlr_data_w(g_io_tech_ddr);  -- 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_io_rd_fifo_depth      : NATURAL := (g_dp_fifo_depth * g_dp_data_w) / func_tech_ddr_ctlr_data_w(g_io_tech_ddr);  -- 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
    
  SIGNAL bg_siso_arr     : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);  -- Default xon='1'
  SIGNAL bg_sosi_arr     : t_dp_sosi_arr(0 DOWNTO 0);                             -- Output SOSI that contains the waveform data

  SIGNAL db_siso_arr     : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);  -- Default ready='1'
  SIGNAL db_sosi_arr     : t_dp_sosi_arr(0 DOWNTO 0);

BEGIN

  ------------------------------------------------------------------------------
  -- IO_DDR
  ------------------------------------------------------------------------------
  u_mms_io_ddr : ENTITY work.mms_io_ddr
  GENERIC MAP (
Eric Kooistra's avatar
Eric Kooistra committed
    g_sim_model               => g_sim_model_ddr,
    g_wr_data_w               => g_dp_data_w,
    g_wr_fifo_depth           => c_io_wr_fifo_depth,
    g_rd_fifo_depth           => c_io_rd_fifo_depth,
    g_rd_data_w               => g_dp_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        => ctlr_ref_clk,
    ctlr_ref_rst        => ctlr_ref_rst,

    -- DDR controller clock domain
    ctlr_clk_out        => ctlr_clk_out,
    ctlr_rst_out        => ctlr_rst_out,

    ctlr_clk_in         => ctlr_clk_in,
    ctlr_rst_in         => ctlr_rst_in,

    -- MM clock + reset
    mm_rst              => mm_rst,
    mm_clk              => mm_clk,

    -- MM interface
    reg_io_ddr_mosi     => reg_io_ddr_mosi,
    reg_io_ddr_miso     => reg_io_ddr_miso,

    -- Write FIFO clock domain
    wr_sosi             => bg_sosi_arr(0),
    wr_siso             => bg_siso_arr(0),
    rd_sosi             => db_sosi_arr(0),
    rd_siso             => db_siso_arr(0),

    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
  );

  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  u_mms_diag_block_gen: ENTITY diag_lib.mms_diag_block_gen
  GENERIC MAP (
    -- Generate configurations
    g_use_usr_input      => FALSE,
    g_use_bg             => FALSE,
    g_use_tx_seq         => TRUE,
  )
  PORT MAP (
    -- System
    mm_rst           => mm_rst,
    mm_clk           => mm_clk,
    dp_rst           => dp_rst,
    dp_clk           => dp_clk,
    -- MM interface
    reg_tx_seq_mosi  => reg_tx_seq_mosi,
    reg_tx_seq_miso  => reg_tx_seq_miso,
    -- ST interface
    out_siso_arr     => bg_siso_arr,
    out_sosi_arr     => bg_sosi_arr
  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  u_mms_diag_data_buffer: ENTITY diag_lib.mms_diag_data_buffer
  GENERIC MAP (
    -- Generate configurations
    g_use_db       => g_db_use_db,
    g_data_type    => e_data,      -- define the sosi field that gets stored: e_data=data, e_complex=im&re, e_real=re, e_imag=im,
    g_data_w       => c_word_w,    -- only capture the lowest c_word_w=32 bits of the g_dp_data_w
    g_buf_use_sync => FALSE,       -- when TRUE start filling the buffer at the in_sync, else after the last word was read,
  )
  PORT MAP (
    -- System
    mm_rst            => mm_rst,
    mm_clk            => mm_clk,
    dp_rst            => dp_rst,
    dp_clk            => dp_clk,
    -- MM interface
    reg_data_buf_mosi => reg_data_buf_mosi,
    reg_data_buf_miso => reg_data_buf_miso,
    ram_data_buf_mosi => ram_data_buf_mosi,
    ram_data_buf_miso => ram_data_buf_miso,
    reg_rx_seq_mosi   => reg_rx_seq_mosi,
    reg_rx_seq_miso   => reg_rx_seq_miso,

    -- ST interface