From 6aeae2e54ec4bda7cef0b1cf63151ea9f0784dc0 Mon Sep 17 00:00:00 2001
From: Pepping <pepping>
Date: Thu, 23 Apr 2015 08:12:27 +0000
Subject: [PATCH] Initial commit

---
 libraries/io/ddr/src/vhdl/io_ddr_reg.vhd | 250 +++++++++++++++++++++++
 libraries/io/ddr/src/vhdl/mms_io_ddr.vhd | 213 +++++++++++++++++++
 2 files changed, 463 insertions(+)
 create mode 100644 libraries/io/ddr/src/vhdl/io_ddr_reg.vhd
 create mode 100644 libraries/io/ddr/src/vhdl/mms_io_ddr.vhd

diff --git a/libraries/io/ddr/src/vhdl/io_ddr_reg.vhd b/libraries/io/ddr/src/vhdl/io_ddr_reg.vhd
new file mode 100644
index 0000000000..1c00111eaa
--- /dev/null
+++ b/libraries/io/ddr/src/vhdl/io_ddr_reg.vhd
@@ -0,0 +1,250 @@
+-------------------------------------------------------------------------------
+--
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+--  RO  read only  (no VHDL present to access HW in write mode)
+--  WO  write only (no VHDL present to access HW in read mode)
+--  WE  write event (=WO)
+--  WR  write control, read control
+--  RW  read status, write control  
+--  RC  read, clear on read
+--  FR  FIFO read
+--  FW  FIFO write
+--
+--  wi  Bits    R/W Name          Default  Description                 |REG_DDR3|                      
+--  =============================================================================
+--  0   [0]     WE  burstbegin    0x0
+--  1   [0]     WO  wr_not_rd     0x0
+--  2   [0]     RO  done          0x1
+--  3   [1..0]  RO  cal_result    0x1      cal_fail & cal_ok
+--  4   [0]     RO  waitrequest_n 0x1
+--  5   [31..0] WO  address       0x0
+--  6   [31..0] WO  burstsize     0x0
+--  7   [0]     WR  flush         0x0
+--  =============================================================================
+
+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;
+
+
+ENTITY io_ddr_reg IS
+  PORT (
+    -- Clocks and reset
+    mm_rst            : IN  STD_LOGIC;  -- reset synchronous with mm_clk
+    mm_clk            : IN  STD_LOGIC;  -- memory-mapped bus clock
+    dp_rst            : IN  STD_LOGIC;  -- reset synchronous with dp_clk
+    dp_clk            : IN  STD_LOGIC;  -- other clock domain clock
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in            : IN  t_mem_mosi; -- actual ranges defined by c_mm_reg
+    sla_out           : OUT t_mem_miso; -- actual ranges defined by c_mm_reg
+    
+    -- MM registers in st_clk domain
+    dvr_miso          : IN  t_mem_ctlr_miso;
+    dvr_mosi          : OUT t_mem_ctlr_mosi
+  );
+END io_ddr_reg;
+
+
+ARCHITECTURE rtl OF io_ddr_reg IS
+
+  CONSTANT c_mm_reg        : t_c_mem := (latency  => 1,
+                                         adr_w    => ceil_log2(8),
+                                         dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                         nof_dat  => 8,
+                                         init_sl  => '0');                                               
+  -- Registers in mm_clk domain
+  SIGNAL mm_dvr_miso       : t_mem_ctlr_miso;
+  SIGNAL mm_dvr_mosi       : t_mem_ctlr_mosi;
+     
+BEGIN
+
+  ------------------------------------------------------------------------------
+  -- MM register access in the mm_clk domain
+  -- . Hardcode the shared MM slave register directly in RTL instead of using
+  --   the common_reg_r_w instance. Directly using RTL is easier when the large
+  --   MM register has multiple different fields and with different read and
+  --   write options per field in one MM register.
+  ------------------------------------------------------------------------------
+  
+  p_mm_reg : PROCESS (mm_rst, mm_clk)
+  BEGIN
+    IF mm_rst = '1' THEN
+      sla_out     <= c_mem_miso_rst;
+      mm_dvr_mosi <= c_mem_ctlr_mosi_rst;
+      
+    ELSIF rising_edge(mm_clk) THEN
+      -- Read access defaults
+      sla_out.rdval <= '0';
+      mm_dvr_mosi.burstbegin <= '0';
+      
+      -- Write access: set register value
+      IF sla_in.wr = '1' THEN
+        CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS
+          -- Write Block Sync
+          WHEN 0 =>            
+            mm_dvr_mosi.burstbegin <= sla_in.wrdata(0);
+          WHEN 1 =>
+            mm_dvr_mosi.wr         <= sla_in.wrdata(0);   
+            mm_dvr_mosi.rd         <= NOT(sla_in.wrdata(0));          
+          WHEN 5 =>                
+            mm_dvr_mosi.address    <= sla_in.wrdata(c_mem_ctlr_address_w-1 DOWNTO 0);
+          WHEN 6 =>        
+            mm_dvr_mosi.burstsize  <= sla_in.wrdata(c_mem_ctlr_burstsize_w-1 DOWNTO 0);
+          WHEN 7 =>            
+            mm_dvr_mosi.flush      <= sla_in.wrdata(0);
+          WHEN OTHERS => NULL;  -- unused MM addresses
+        END CASE;
+
+      -- Read access: get register value
+      ELSIF sla_in.rd = '1' THEN
+        sla_out       <= c_mem_miso_rst;    -- set unused rddata bits to '0' when read
+        sla_out.rdval <= '1';               -- c_mm_reg.latency = 1
+        CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS
+          -- Read Block Sync
+          WHEN 2 =>            
+            sla_out.rddata(0) <= mm_dvr_miso.done;
+          WHEN 3 =>
+            sla_out.rddata(1 DOWNTO 0) <= mm_dvr_miso.cal_fail & mm_dvr_miso.cal_ok;
+          WHEN 4 =>
+            sla_out.rddata(0) <= mm_dvr_miso.waitrequest_n;   
+          WHEN 7 => 
+            sla_out.rddata(0) <= mm_dvr_mosi.flush;    
+          WHEN OTHERS => NULL;  -- unused MM addresses
+        END CASE;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  ------------------------------------------------------------------------------
+  -- Transfer register value between mm_clk and st_clk domain.
+  -- If the function of the register ensures that the value will not be used
+  -- immediately when it was set, then the transfer between the clock domains
+  -- can be done by wires only. Otherwise if the change in register value can
+  -- have an immediate effect then the bit or word value needs to be transfered
+  -- using:
+  --
+  -- . common_async            --> for single-bit level signal
+  -- . common_spulse           --> for single-bit pulse signal
+  -- . common_reg_cross_domain --> for a multi-bit (a word) signal
+  --
+  -- Typically always use a crossing component for the single bit signals (to
+  -- be on the safe side) and only use a crossing component for the word
+  -- signals if it is necessary (to avoid using more logic than necessary).
+  ------------------------------------------------------------------------------
+  
+  u_spulse_en_evt : ENTITY common_lib.common_spulse
+  PORT MAP (
+    in_rst    => mm_rst,
+    in_clk    => mm_clk,
+    in_pulse  => mm_dvr_mosi.burstbegin,
+    in_busy   => OPEN,
+    out_rst   => dp_rst,
+    out_clk   => dp_clk,
+    out_pulse => dvr_mosi.burstbegin
+  );
+ 
+  u_async_wr : ENTITY common_lib.common_async
+  GENERIC MAP (
+    g_rst_level => '0'
+  )
+  PORT MAP (
+    rst  => dp_rst,
+    clk  => dp_clk,
+    din  => mm_dvr_mosi.wr,
+    dout => dvr_mosi.wr
+  );
+
+  u_async_rd : ENTITY common_lib.common_async
+  GENERIC MAP (
+    g_rst_level => '0'
+  )
+  PORT MAP (
+    rst  => dp_rst,
+    clk  => dp_clk,
+    din  => mm_dvr_mosi.rd,
+    dout => dvr_mosi.rd
+  );
+
+  u_async_flush : ENTITY common_lib.common_async
+  GENERIC MAP (
+    g_rst_level => '0'
+  )
+  PORT MAP (
+    rst  => dp_rst,
+    clk  => dp_clk,
+    din  => mm_dvr_mosi.flush,
+    dout => dvr_mosi.flush
+  );
+
+  u_async_done : ENTITY common_lib.common_async
+  GENERIC MAP (
+    g_rst_level => '0'
+  )
+  PORT MAP (
+    rst  => mm_rst,
+    clk  => mm_clk,
+    din  => dvr_miso.done,
+    dout => mm_dvr_miso.done
+  );
+
+  u_async_waitrequest_n : ENTITY common_lib.common_async
+  GENERIC MAP (
+    g_rst_level => '0'
+  )
+  PORT MAP (
+    rst  => mm_rst,
+    clk  => mm_clk,
+    din  => dvr_miso.waitrequest_n,
+    dout => mm_dvr_miso.waitrequest_n
+  );
+
+  mm_dvr_miso.cal_fail <= dvr_miso.cal_fail;
+  mm_dvr_miso.cal_ok   <= dvr_miso.cal_ok;
+
+  u_cross_domain_addr : ENTITY common_lib.common_reg_cross_domain
+  PORT MAP (
+    in_rst      => mm_rst,
+    in_clk      => mm_clk,
+    in_dat      => mm_dvr_mosi.address,
+    in_done     => OPEN,
+    out_rst     => dp_rst,
+    out_clk     => dp_clk,
+    out_dat     => dvr_mosi.address,
+    out_new     => OPEN
+  );
+
+  u_cross_domain_burstsize : ENTITY common_lib.common_reg_cross_domain
+  PORT MAP (
+    in_rst      => mm_rst,
+    in_clk      => mm_clk,
+    in_dat      => mm_dvr_mosi.burstsize,
+    in_done     => OPEN,
+    out_rst     => dp_rst,
+    out_clk     => dp_clk,
+    out_dat     => dvr_mosi.burstsize,
+    out_new     => OPEN
+  );
+ 
+END rtl;
+
diff --git a/libraries/io/ddr/src/vhdl/mms_io_ddr.vhd b/libraries/io/ddr/src/vhdl/mms_io_ddr.vhd
new file mode 100644
index 0000000000..3a03de15ff
--- /dev/null
+++ b/libraries/io/ddr/src/vhdl/mms_io_ddr.vhd
@@ -0,0 +1,213 @@
+
+-------------------------------------------------------------------------------
+--
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.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 tech_ddr_lib.tech_ddr_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+ENTITY mms_io_ddr IS
+  GENERIC(
+    g_technology              : NATURAL := c_tech_select_default;
+    g_tech_ddr                : t_c_tech_ddr;
+    g_cross_domain_dvr_ctlr   : BOOLEAN := TRUE;
+    g_cross_domain_delay_len  : NATURAL := c_meta_delay_len;
+    g_wr_data_w               : NATURAL := 32;  
+    g_wr_fifo_depth           : NATURAL := 256;     -- >=16                             , defined at DDR side of the FIFO, default 256 because 32b*256 fits in 1 M9K
+    g_rd_fifo_depth           : NATURAL := 256;     -- >=16 AND >g_tech_ddr.maxburstsize, defined at DDR side of the FIFO, default 256 because 32b*256 fits in 1 M9K 
+    g_rd_fifo_af_margin       : NATURAL := 4 + 1*64;  -- < g_rd_fifo_depth and sufficient to fit one or more rd burst accesses of g_tech_ddr.maxburstsize each
+    g_rd_data_w               : NATURAL := 32;
+    g_wr_flush_mode           : STRING := "VAL";  -- "VAL", "SOP", "SYN"
+    g_wr_flush_use_channel    : BOOLEAN := FALSE;
+    g_wr_flush_start_channel  : NATURAL := 0;
+    g_wr_flush_nof_channels   : POSITIVE := 1
+  );                      
+  PORT (
+    -- 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 clock + reset 
+    mm_rst              : IN    STD_LOGIC := '1';                                           
+    mm_clk              : IN    STD_LOGIC := '0'; 
+                        
+    -- 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;
+    
+    dvr_clk             : IN    STD_LOGIC;
+    dvr_rst             : IN    STD_LOGIC;
+                        
+    -- Write FIFO clock domain
+    wr_clk              : IN    STD_LOGIC;
+    wr_rst              : IN    STD_LOGIC;
+                        
+    wr_fifo_usedw       : OUT   STD_LOGIC_VECTOR(ceil_log2(g_wr_fifo_depth * (func_tech_ddr_ctlr_data_w(g_tech_ddr)/g_wr_data_w) )-1 DOWNTO 0);  -- for monitoring purposes
+    wr_sosi             : IN    t_dp_sosi;
+    wr_siso             : OUT   t_dp_siso;
+  
+    -- Read FIFO clock domain
+    rd_clk              : IN    STD_LOGIC;
+    rd_rst              : IN    STD_LOGIC;
+                        
+    rd_fifo_usedw       : OUT   STD_LOGIC_VECTOR(ceil_log2(g_rd_fifo_depth * (func_tech_ddr_ctlr_data_w(g_tech_ddr)/g_rd_data_w) )-1 DOWNTO 0);    
+    rd_sosi             : OUT   t_dp_sosi;
+    rd_siso             : IN    t_dp_siso;
+                        
+    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
+  );
+END mms_io_ddr;
+
+
+ARCHITECTURE str OF mms_io_ddr IS
+
+  SIGNAL ctlr_dvr_miso : t_mem_ctlr_miso;
+  SIGNAL ctlr_dvr_mosi : t_mem_ctlr_mosi;
+  
+  SIGNAL reg_io_ddr_mosi_arr : t_mem_mosi_arr(1 DOWNTO 0); 
+  SIGNAL reg_io_ddr_miso_arr : t_mem_miso_arr(1 DOWNTO 0); 
+
+BEGIN
+
+  -- Combine the reg map of io_ddr and io_ddr_reg
+  u_mm_mux : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (    
+    g_nof_mosi    => 2,
+    g_mult_addr_w => ceil_log2(8)
+  )
+  PORT MAP (
+    mosi     => reg_io_ddr_mosi,
+    miso     => reg_io_ddr_miso,
+    mosi_arr => reg_io_ddr_mosi_arr,
+    miso_arr => reg_io_ddr_miso_arr
+  );
+
+  u_ddr_mem_ctrl : ENTITY work.io_ddr
+  GENERIC MAP( 
+    g_technology             => g_technology,
+    g_tech_ddr               => g_tech_ddr,
+    g_cross_domain_dvr_ctlr  => FALSE, 
+    g_wr_data_w              => g_wr_data_w,     
+    g_wr_fifo_depth          => g_wr_fifo_depth, 
+    g_rd_fifo_depth          => g_rd_fifo_depth, 
+    g_rd_data_w              => g_rd_data_w,     
+    g_wr_flush_mode          => g_wr_flush_mode,           
+    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,   -- output clock of the ddr controller is used as DP clk.
+    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 register map for DDR controller status info
+    reg_io_ddr_mosi => reg_io_ddr_mosi_arr(0),
+    reg_io_ddr_miso => reg_io_ddr_miso_arr(0),
+
+    -- Driver clock domain
+    dvr_clk       => dvr_clk,
+    dvr_rst       => dvr_rst,
+    
+    dvr_miso      => ctlr_dvr_miso,
+    dvr_mosi      => ctlr_dvr_mosi,
+
+    -- Write FIFO clock domain
+    wr_clk        => wr_clk,
+    wr_rst        => wr_rst,
+
+    wr_fifo_usedw => OPEN,
+    wr_sosi       => wr_sosi,  
+    wr_siso       => wr_siso,
+  
+    -- Read FIFO clock domain
+    rd_clk        => rd_clk,
+    rd_rst        => rd_rst,     
+    
+    rd_fifo_usedw => OPEN,
+    rd_sosi       => rd_sosi,
+    rd_siso       => rd_siso,
+
+    term_ctrl_out => OPEN,
+    term_ctrl_in  => OPEN,
+    
+    phy3_in       => phy3_in,
+    phy3_io       => phy3_io,  
+    phy3_ou       => phy3_ou,
+
+    phy4_in       => phy4_in,
+    phy4_io       => phy4_io,  
+    phy4_ou       => phy4_ou
+  );             
+
+  u_ddr_reg : ENTITY work.io_ddr_reg 
+  PORT MAP(
+    -- Clocks and reset
+    mm_rst          => mm_rst,
+    mm_clk          => mm_clk, 
+    dp_rst          => dvr_rst,  
+    dp_clk          => dvr_clk,  
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in          => reg_io_ddr_mosi_arr(1),
+    sla_out         => reg_io_ddr_miso_arr(1),
+    
+    -- MM registers in st_clk domain
+    dvr_miso        => ctlr_dvr_miso,
+    dvr_mosi        => ctlr_dvr_mosi
+  );
+
+END str;
+
-- 
GitLab