Skip to content
Snippets Groups Projects
Select Git revision
  • 1830f99b3536c9a0f6dfb10d9657b8a6c543b9ab
  • master default protected
  • esap-gui-auth
  • esap-gui-dev
4 results

Main.js

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ddr3.vhd 14.41 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/>.
    --
    --------------------------------------------------------------------------------
    
    -- Declare IP libraries to ensure default binding in simulation. The IP library clause is ignored by synthesis.
    library ip_stratixiv_ddr3_uphy_4g_800_master_lib;
    library ip_stratixiv_ddr3_uphy_4g_800_slave_lib;
    
    library IEEE, common_lib, technology_lib, dp_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 technology_lib.technology_select_pkg.all;
    use technology_lib.technology_pkg.all;
    use dp_lib.dp_stream_pkg.all;
    use tech_ddr_lib.tech_ddr_pkg.all;
    use work.ddr3_pkg.all;
    
    entity ddr3 is
      generic(
        g_phy                     : natural := 1;  -- 0: ALTMEMPHY  1: UNIPHY_MASTER 2: UNIPHY_SLAVE
        g_ddr                     : t_c_ddr3_phy;
        g_mts                     : natural := 800;  -- Megatransfers per second
        g_wr_data_w               : natural := c_ddr3_ctlr_data_w;
        g_wr_use_ctrl             : boolean := false;  -- TRUE to allow filling the WR FIFO (by disabling flush) after an EOP
        g_wr_fifo_depth           : natural := 128;  -- >=16 AND >c_ddr3_ctlr_maxburstsize                               , defined at read  side of write FIFO.
        g_rd_fifo_depth           : natural := 256;  -- >=16 AND >c_ddr3_ctlr_maxburstsize > c_ddr3_ctrl_nof_latent_reads, defined at write side of read  FIFO.
        g_rd_data_w               : natural := c_ddr3_ctlr_data_w;
        g_flush_wr_fifo           : boolean := false;  -- TRUE instantiates a dp_flush + controller to flush the write fifo when the driver is not ready to write
        g_flush_ext_ena           : boolean := false;  -- TRUE enables the external flush_ena signal and discards flushing when driver is not ready. FALSE enables flushing when driver is not ready
        g_flush_sop               : boolean := false;  -- When FALSE, flushing is stopped by valid data. When TRUE flushing is stopped by SOP
        g_flush_sop_sync          : boolean := false;  -- When TRUE, flushing is stopped by receiving SOP and SYNC
        g_flush_sop_channel       : boolean := false;  -- WHEN TRUE, flushing is stopped by receiving SOP and specified channel.
        g_flush_sop_start_channel : natural := 0;
        g_flush_nof_channels      : natural := 0
      );
      port (
        -- MM clock + reset
        mm_rst             : in    std_logic := '0';
        mm_clk             : in    std_logic := '0';
    
        ctlr_ref_clk       : in    std_logic;
        ctlr_rst           : in    std_logic;  -- asynchronous reset input to controller
    
        ctlr_gen_clk       : out   std_logic;  -- Controller generated clock
        ctlr_gen_rst       : out   std_logic;
        ctlr_gen_clk_2x    : out   std_logic;  -- Controller generated double frequency clock
        ctlr_gen_rst_2x    : out   std_logic;  -- ctlr_gen_rst synchronized to ctlr_gen_clk_2x
    
        ctlr_init_done     : out   std_logic;
        ctlr_rdy           : out   std_logic;
    
        dvr_start_addr     : in    t_ddr3_addr;
        dvr_end_addr       : in    t_ddr3_addr;
    
        dvr_en             : in    std_logic;
        dvr_wr_not_rd      : in    std_logic;
        dvr_done           : out   std_logic;
    
        wr_clk             : in    std_logic;
        wr_rst             : in    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 := c_mem_miso_rst;
    
        flush_ena          : in    std_logic;  -- When toggled '1' the write-fifo flusher is enabled and stops flushing when configured trigger condition is met.
    
        wr_sosi            : in    t_dp_sosi;
        wr_siso            : out   t_dp_siso;
    
        rd_sosi            : out   t_dp_sosi;
        rd_siso            : in    t_dp_siso;
    
        rd_clk             : in    std_logic;
        rd_rst             : in    std_logic;
    
        rd_fifo_usedw      : out   std_logic_vector(ceil_log2(g_rd_fifo_depth * (c_ddr3_ctlr_data_w / g_rd_data_w) ) - 1 downto 0);
    
        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;
    
    architecture str of ddr3 is
      constant c_wr_fifo_depth  : natural := g_wr_fifo_depth * (c_ddr3_ctlr_data_w / g_wr_data_w);  -- Multiply fifo depth by the fifo's rd/wr width ratio to get write side depth
    
      constant c_latency        : natural := 1;
    
      constant c_ctlr_address_w : natural := func_tech_ddr_ctlr_address_w(c_tech_ddr3_4g_800m_master);
      constant c_ctlr_data_w    : natural := func_tech_ddr_ctlr_data_w(c_tech_ddr3_4g_800m_master);
    
      signal ctlr_burst         : std_logic;
      signal ctlr_burst_size    : std_logic_vector(c_ddr3_ctlr_maxburstsize_w - 1 downto 0);
      signal ctlr_rd_req        : std_logic;
      signal ctlr_wr_req        : std_logic;
    
      signal ctlr_gen_rst_n     : std_logic;
    
      signal i_ctlr_gen_clk     : std_logic;
      signal i_ctlr_gen_rst     : std_logic;
      signal i_ctlr_gen_clk_2x  : std_logic;
      signal i_ctlr_init_done   : std_logic;
      signal i_ctlr_rdy         : std_logic;
      signal i_dvr_done         : std_logic;
    
      signal dvr_cur_addr       : t_ddr3_addr;
      signal dvr_flush          : std_logic := '0';
    
      signal ctlr_wr_siso       : t_dp_siso := c_dp_siso_rdy;  -- default xon='1'
      signal ctlr_wr_sosi       : t_dp_sosi;
    
      signal flush_wr_siso      : t_dp_siso;
      signal flush_wr_sosi      : t_dp_sosi;
    
      signal ctlr_rd_siso       : t_dp_siso;
      signal ctlr_rd_sosi       : t_dp_sosi;
    
      signal wr_fifo_usedw      : std_logic_vector(ceil_log2(g_wr_fifo_depth) - 1 downto 0);  -- read side depth of the write FIFO
    
      signal local_cal_success  : std_logic;
      signal local_cal_fail     : std_logic;
    
      constant c_mem_reg_io_ddr : t_c_mem := (c_mem_reg_rd_latency, 1,  32,  1, 'X');
      signal mm_reg_io_ddr      : std_logic_vector(31 downto 0);
    
      signal term_ctrl_out      : t_tech_ddr3_phy_terminationcontrol;
      signal term_ctrl_in       : t_tech_ddr3_phy_terminationcontrol;
    
      signal ctlr_tech_mosi     : t_mem_ctlr_mosi;
      signal ctlr_tech_miso     : t_mem_ctlr_miso;
    begin
      dvr_done <= i_dvr_done;
    
      ctlr_gen_clk    <= i_ctlr_gen_clk;
      ctlr_gen_rst    <= i_ctlr_gen_rst;
      ctlr_gen_clk_2x <= i_ctlr_gen_clk_2x;
      ctlr_rdy        <= i_ctlr_rdy;
      ctlr_init_done  <= i_ctlr_init_done;
    
      u_wr_fifo : entity dp_lib.dp_fifo_dc_mixed_widths
      generic map (
        g_wr_data_w         => g_wr_data_w,
        g_rd_data_w         => c_ddr3_ctlr_data_w,
        g_use_ctrl          => g_wr_use_ctrl,
        g_wr_fifo_size      => c_wr_fifo_depth,
        g_wr_fifo_af_margin => 4 + c_latency,  -- default (4) + c_latency to compensate for latency introduced by registering wr_siso.ready
        g_rd_fifo_rl        => 0
      )
      port map (
        wr_rst         => wr_rst,
        wr_clk         => wr_clk,
        rd_rst         => i_ctlr_gen_rst,
        rd_clk         => i_ctlr_gen_clk,
    
        snk_out        => wr_siso,
        snk_in         => wr_sosi,
    
        wr_usedw       => OPEN,
        rd_usedw       => wr_fifo_usedw,
        rd_emp         => OPEN,
    
        src_in         => flush_wr_siso,
        src_out        => flush_wr_sosi
      );
    
      u_dp_flush : entity dp_lib.dp_flush  -- Always instantiate the flusher as it also contains a RL adapter
      generic map (
        g_ready_latency => 0,
        g_framed_xon    => g_wr_use_ctrl,  -- stop flushing when dvr_flush is low and a sop has arrived
        g_framed_xoff   => false  -- immediately start flushing when dvr_flush goes high
      )
      port map (
        rst      => i_ctlr_gen_rst,
        clk      => i_ctlr_gen_clk,
    
        snk_in   => flush_wr_sosi,
        snk_out  => flush_wr_siso,
    
        src_out  => ctlr_wr_sosi,
        src_in   => ctlr_wr_siso,  -- fixed streaming xon='1'
    
        flush_en => dvr_flush  -- memory mapped xon/xoff control
      );
    
      gen_flush : if g_flush_wr_fifo = true generate
        u_flush_ctrl : entity work.ddr3_flush_ctrl
        generic map (
          g_ext_ena           => g_flush_ext_ena,
          g_sop               => g_flush_sop,
          g_sop_sync          => g_flush_sop_sync,
          g_sop_channel       => g_flush_sop_channel,
          g_sop_start_channel => g_flush_sop_start_channel,
          g_nof_channels      => g_flush_nof_channels
        )
        port map (
          rst           => wr_rst,
          clk           => wr_clk,
    
          dvr_en        => dvr_en,
          dvr_wr_not_rd => dvr_wr_not_rd,
          dvr_done      => i_dvr_done,
    
          wr_sosi       => wr_sosi,
          flush_ena     => flush_ena,
    
          dvr_flush     => dvr_flush
        );
      end generate;
    
      u_rd_fifo : entity dp_lib.dp_fifo_dc_mixed_widths
      generic map (
        g_wr_data_w         => c_ddr3_ctlr_data_w,
        g_rd_data_w         => g_rd_data_w,
        g_use_ctrl          => false,
        g_wr_fifo_size      => g_rd_fifo_depth,
        g_wr_fifo_af_margin => c_ddr3_ctrl_nof_latent_reads,  -- >=4 (required by dp_fifo)
        g_rd_fifo_rl        => 1
      )
      port map (
        wr_rst   => i_ctlr_gen_rst,
        wr_clk   => i_ctlr_gen_clk,
        rd_rst   => rd_rst,
        rd_clk   => rd_clk,
    
        snk_out  => ctlr_rd_siso,
        snk_in   => ctlr_rd_sosi,
    
        wr_usedw => OPEN,
        rd_usedw => rd_fifo_usedw,
        rd_emp   => OPEN,
    
        src_in   => rd_siso,
        src_out  => rd_sosi
      );
    
      u_ddr3_driver : entity work.ddr3_driver
      generic map (
        g_wr_fifo_depth => g_wr_fifo_depth,
        g_ddr           => g_ddr
      )
      port map (
        rst             => i_ctlr_gen_rst,
        clk             => i_ctlr_gen_clk,
    
        ctlr_rdy        => i_ctlr_rdy,
        ctlr_init_done  => i_ctlr_init_done,
        ctlr_wr_req     => ctlr_wr_req,
        ctlr_rd_req     => ctlr_rd_req,
        ctlr_burst      => ctlr_burst,
        ctlr_burst_size => ctlr_burst_size,
    
        wr_val          => ctlr_wr_sosi.valid,
        wr_rdy          => ctlr_wr_siso.ready,
        rd_rdy          => ctlr_rd_siso.ready,
    
        cur_addr        => dvr_cur_addr,
        start_addr      => dvr_start_addr,
        end_addr        => dvr_end_addr,
    
        dvr_en          => dvr_en,
        dvr_wr_not_rd   => dvr_wr_not_rd,
        dvr_done        => i_dvr_done,
    
        wr_fifo_usedw   => wr_fifo_usedw
      );
    
      u_reg_map : entity common_lib.common_reg_r_w_dc
      generic map (
        g_cross_clock_domain => true,  -- : BOOLEAN := TRUE;  -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain
        g_in_new_latency     => 0,  -- : NATURAL := 0;  -- >= 0
        g_readback           => false,  -- : BOOLEAN := FALSE;  -- must use FALSE for write/read or read only register when g_cross_clock_domain=TRUE
        g_reg                => c_mem_reg_io_ddr,  -- : t_c_mem := c_mem_reg;
        g_init_reg           => (others => '0')  -- : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := (OTHERS => '0')
      )
      port map (
        -- Clocks and reset
        mm_rst      => mm_rst,  -- : IN  STD_LOGIC;   -- reset synchronous with mm_clk
        mm_clk      => mm_clk,  -- : IN  STD_LOGIC;   -- memory-mapped bus clock
        st_rst      => i_ctlr_gen_rst,  -- : IN  STD_LOGIC;   -- reset synchronous with st_clk
        st_clk      => i_ctlr_gen_clk,  -- : IN  STD_LOGIC;   -- other clock domain clock
    
        -- Memory Mapped Slave in mm_clk domain
        sla_in      => reg_io_ddr_mosi,  -- : IN  t_mem_mosi;  -- actual ranges defined by g_reg
        sla_out     => reg_io_ddr_miso,  -- : OUT t_mem_miso;  -- actual ranges defined by g_reg
    
        -- MM registers in st_clk domain
        reg_wr_arr  => OPEN,  -- : OUT STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
        reg_rd_arr  => OPEN,  -- : OUT STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
        in_new      => '1',  -- : IN  STD_LOGIC := '1';
        in_reg      => mm_reg_io_ddr,  -- : IN  STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0);
        out_reg     => open  -- : OUT STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0)
      );
    
      mm_reg_io_ddr <= RESIZE_UVEC(local_cal_fail & local_cal_success & i_ctlr_gen_rst & flush_ena & i_ctlr_rdy & i_ctlr_init_done, 32);
    
      ser_term_ctrl_out <= term_ctrl_out.seriesterminationcontrol;
      par_term_ctrl_out <= term_ctrl_out.parallelterminationcontrol;
      term_ctrl_in.seriesterminationcontrol   <= ser_term_ctrl_in;
      term_ctrl_in.parallelterminationcontrol <= par_term_ctrl_in;
    
      ctlr_tech_mosi.burstbegin <= ctlr_burst;
      ctlr_tech_mosi.address    <= RESIZE_MEM_CTLR_ADDRESS(dvr_cur_addr.chip & dvr_cur_addr.bank & dvr_cur_addr.row(g_ddr.a_w - 1 downto 0) & dvr_cur_addr.column(g_ddr.a_col_w - 1 downto c_ddr3_ctlr_rsl_w));
      ctlr_tech_mosi.wrdata     <= RESIZE_MEM_CTLR_DATA(ctlr_wr_sosi.data);
      ctlr_tech_mosi.rd         <= ctlr_rd_req;
      ctlr_tech_mosi.wr         <= ctlr_wr_req;
      ctlr_tech_mosi.burstsize  <= RESIZE_MEM_CTLR_BURSTSIZE(ctlr_burst_size);
    
      i_ctlr_rdy          <= ctlr_tech_miso.waitrequest_n;
      ctlr_rd_sosi.valid  <= ctlr_tech_miso.rdval;
      ctlr_rd_sosi.data   <= RESIZE_DP_DATA(ctlr_tech_miso.rddata);
      i_ctlr_init_done    <= ctlr_tech_miso.done;
      local_cal_success   <= ctlr_tech_miso.cal_ok;
      local_cal_fail      <= ctlr_tech_miso.cal_fail;
    
      u_tech_ddr : entity tech_ddr_lib.tech_ddr
      generic map (
        g_technology    => c_tech_stratixiv,
        g_tech_ddr      => c_tech_ddr3_4g_800m_master
      )
      port map (
        -- PLL reference clock
        ref_clk         => ctlr_ref_clk,
        ref_rst         => ctlr_rst,
    
        -- Controller user interface
        ctlr_gen_clk    => i_ctlr_gen_clk,
        ctlr_gen_rst    => i_ctlr_gen_rst,
        ctlr_gen_clk_2x => i_ctlr_gen_clk_2x,
        ctlr_gen_rst_2x => ctlr_gen_rst_2x,
    
        ctlr_mosi       => ctlr_tech_mosi,
        ctlr_miso       => ctlr_tech_miso,
    
        term_ctrl_out   => term_ctrl_out,
        term_ctrl_in    => term_ctrl_in,
    
        -- DDR3 PHY interface
        phy3_in         => phy_in,
        phy3_io         => phy_io,
        phy3_ou         => phy_ou
      );
    end str;