Skip to content
Snippets Groups Projects
Select Git revision
  • 08d9a16e8f3ad2c16d587f3d0024de3f6fedb1d9
  • master default protected
  • L2SDP-LIFT
  • L2SDP-1113
  • HPR-158
5 results

sim_ddr.vhd

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    sim_ddr.vhd 5.29 KiB
    --------------------------------------------------------------------------------
    --
    -- Copyright (C) 2015
    -- 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/>.
    --
    --------------------------------------------------------------------------------
    
    -- Purpose: Functional simulation model of both the DDR driver and the DDR memory.
    -- Description:
    --   The component also supports different types of DDR, so DDR3 and DDR4.
    -- Remark:
    -- . It is assumed that the user only performs burst reads/writes!
    -- . Modelsim raises warning 3391 when the DDR memory set by c_nof_addr is to big to fit in PC RAM.
    --   Use 'verror 3391' to display the help. This means that the computer becomes too slow due to
    --   page swapping to disk. Even loading the simulation becomes slow.
    
    LIBRARY IEEE, common_lib, technology_lib;
    USE IEEE.STD_LOGIC_1164.ALL;
    USE common_lib.common_pkg.ALL;
    USE common_lib.common_mem_pkg.ALL;
    USE technology_lib.technology_pkg.ALL;
    USE technology_lib.technology_select_pkg.ALL;
    USE work.tech_ddr_pkg.ALL;
    
    ENTITY sim_ddr IS
      GENERIC (
        g_tech_ddr        : t_c_tech_ddr
      );
      PORT (
        -- PLL reference clock
        ref_clk           : IN    STD_LOGIC;
        ref_rst           : IN    STD_LOGIC;
    
        -- Controller user interface
        ctlr_gen_clk      : OUT   STD_LOGIC;
        ctlr_gen_rst      : OUT   STD_LOGIC;
        ctlr_gen_clk_2x   : OUT   STD_LOGIC;
        ctlr_gen_rst_2x   : OUT   STD_LOGIC;
    
        ctlr_mosi         : IN    t_mem_ctlr_mosi;
        ctlr_miso         : OUT   t_mem_ctlr_miso
      );
    END sim_ddr;
    
    
    ARCHITECTURE str OF sim_ddr IS
    
      -- DDR size and controller data width
      CONSTANT c_nof_addr : NATURAL := 2**func_tech_ddr_ctlr_address_w(g_tech_ddr);  --8192;
      CONSTANT c_dat_w    : NATURAL := func_tech_ddr_ctlr_data_w(g_tech_ddr);  --256;
    
      -- DDR memory
      TYPE t_mem_arr IS ARRAY(0 TO c_nof_addr-1) OF STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0);
    
      SIGNAL sim_clk       : STD_LOGIC;
      SIGNAL sim_rst       : STD_LOGIC;
      SIGNAL sim_ctlr_mosi : t_mem_ctlr_mosi;
    
      SIGNAL address       : NATURAL;
    
    BEGIN
    
      -- Prevent delta delay issues by using a re-assigned clk both internally (sim_clk) and externally (ctrl_gen_clk)
      ctlr_gen_clk <= ref_clk;
      ctlr_gen_rst <= ref_rst;
      sim_clk      <= ref_clk;
      sim_rst      <= ref_rst;
    
      ctlr_miso.done     <= '0' , '1' AFTER 1 ns;
      ctlr_miso.cal_ok   <= '0' , '1' AFTER 1 ns;
      ctlr_miso.cal_fail <= '0';
    
      -- Delay the control one cycle here so p_mem_access can update its outputs immediately
      p_clk : PROCESS(sim_clk)
      BEGIN
        IF rising_edge(sim_clk) THEN
          sim_ctlr_mosi <= ctlr_mosi;
        END IF;
      END PROCESS;
    
      p_mem_access : PROCESS(sim_clk, sim_ctlr_mosi)
        VARIABLE v_enable_model  : BOOLEAN := FALSE;
        VARIABLE v_mem_arr       : t_mem_arr := (OTHERS=>(OTHERS=>'0'));
        VARIABLE v_address       : NATURAL := 0;
        VARIABLE v_wr_bursting   : BOOLEAN := FALSE;
        VARIABLE v_rd_bursting   : BOOLEAN := FALSE;
        VARIABLE v_burst_cnt     : NATURAL := 0;
        VARIABLE v_burst_size    : NATURAL := 0;
      BEGIN
    
        -- Don't waste simulation time when user does not access the model anyway
        IF v_enable_model = FALSE THEN
          ctlr_miso.waitrequest_n <= '1'; 
          IF sim_ctlr_mosi.burstbegin='1' THEN
            v_enable_model := TRUE;
          END IF;
        END IF;
    
        IF v_enable_model = TRUE THEN
          IF rising_edge(sim_clk) THEN
      
            ctlr_miso.rdval <= '0'; 
            ctlr_miso.waitrequest_n <= '1'; 
      
            -- Access: burst begin
            IF sim_ctlr_mosi.burstbegin='1' THEN
              IF sim_ctlr_mosi.wr='1' THEN
                v_wr_bursting := TRUE;
              ELSIF sim_ctlr_mosi.rd='1' THEN
                v_rd_bursting := TRUE;
              END IF;
              v_address     := TO_UINT(sim_ctlr_mosi.address);
              v_burst_size  := TO_UINT(sim_ctlr_mosi.burstsize);
              v_burst_cnt   := 0;
            END IF;
        
            IF v_wr_bursting=TRUE OR v_rd_bursting=TRUE THEN
              IF sim_ctlr_mosi.wr='1' THEN -- Write
                v_mem_arr(v_address) := sim_ctlr_mosi.wrdata(c_dat_w-1 DOWNTO 0);
                v_address   := v_address+1;
                v_burst_cnt := v_burst_cnt +1;
              ELSIF v_rd_bursting=TRUE THEN -- Read
                ctlr_miso.rddata(c_dat_w-1 DOWNTO 0) <= v_mem_arr(v_address);  
                ctlr_miso.rdval <= '1';
                ctlr_miso.waitrequest_n <= '0';
                v_address   := v_address+1;
                v_burst_cnt := v_burst_cnt +1;
              END IF;
        
              IF v_burst_cnt = v_burst_size THEN
                v_wr_bursting := FALSE;
                v_rd_bursting := FALSE;
              END IF;
            END IF;
        
            address <= v_address;
      
          END IF;
        END IF;
    
      END PROCESS;
     
    END str;