📄 ddrctrl.vhd
字号:
-------------------------------------------------------------------------------- This file is a part of the GRLIB VHDL IP LIBRARY-- Copyright (C) 2003, Gaisler Research---- 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 2 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, write to the Free Software-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- Entity: ddrctrl-- File: ddrctrl.vhd-- Author: David Lindh - Gaisler Research-- Description: DDR-RAM memory controller with AMBA interface------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library grlib;use grlib.amba.all;use grlib.stdlib.all;library gaisler;use grlib.devices.all;use gaisler.memctrl.all;library techmap;use techmap.gencomp.all;use techmap.allmem.all;use gaisler.ddrrec.all;entity ddrctrl is generic ( hindex1 : integer := 0; haddr1 : integer := 0; hmask1 : integer := 16#f80#; hindex2 : integer := 0; haddr2 : integer := 0; hmask2 : integer := 16#f80#; pindex : integer := 3; paddr : integer := 0; numahb : integer := 1; -- Allowed: 1, 2 ahb1sepclk : integer := 0; -- Allowed: 0, 1 ahb2sepclk : integer := 0; -- Allowed: 0, 1 modbanks : integer := 1; -- Allowed: 1, 2 numchips : integer := 2; -- Allowed: 1, 2, 4, 8, 16 chipbits : integer := 16; -- Allowed: 4, 8, 16 chipsize : integer := 256; -- Allowed: 64, 128, 256, 512, 1024 (MB) plldelay : integer := 0; -- Allowed: 0, 1 (Use 200us start up delay) tech : integer := virtex2; clkperiod : integer := 10); -- (ns) port ( rst : in std_ulogic; clk0 : in std_ulogic; clk90 : in std_ulogic; clk180 : in std_ulogic; clk270 : in std_ulogic; hclk1 : in std_ulogic; hclk2 : in std_ulogic; pclk : in std_ulogic; ahb1si : in ahb_slv_in_type; ahb1so : out ahb_slv_out_type; ahb2si : in ahb_slv_in_type; ahb2so : out ahb_slv_out_type; apbsi : in apb_slv_in_type; apbso : out apb_slv_out_type; ddsi : out ddrmem_in_type; ddso : in ddrmem_out_type);end ddrctrl;architecture rtl of ddrctrl is------------------------------------------------------------------------------- -- Constants------------------------------------------------------------------------------- constant DELAY_15600NS : integer := (15600 / clkperiod); constant DELAY_7800NS : integer := (7800 / clkperiod); constant DELAY_7_15600NS : integer := (7*(15600 / clkperiod)); constant DELAY_7_7800NS : integer := (7*(7800 / clkperiod)); constant DELAY_200US : integer := (200000 / clkperiod); constant REVISION : integer := 0; constant pmask : integer := 16#fff#; constant pconfig : apb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_DDRMP, 0, REVISION, 0), 1 => apb_iobar(paddr, pmask)); constant dqsize : integer := numchips*chipbits; constant dmsize : integer := (dqsize/8); constant strobesize : integer := (dqsize/8) * dmvector(chipbits); --------------------------------------------------------------------------------- Signals------------------------------------------------------------------------------- signal toAHB : two_ahb_ctrl_in_type; signal fromAHB : two_ahb_ctrl_out_type; signal fromAHB2Main : two_ahb_ctrl_out_type; signal apbr : apb_reg_type; signal apbri : apb_reg_type; signal fromAPB : apb_ctrl_out_type; signal fromAPB2Main : apb_ctrl_out_type; signal mainr : main_reg_type; signal mainri : main_reg_type; signal fromMain : main_ctrl_out_type; signal fromMain2APB : apb_ctrl_in_type; signal fromMain2AHB : two_ahb_ctrl_in_type; signal fromMain2HS : hs_in_type; signal toHS : hs_in_type; signal fromHS : hs_out_type; begin -- achitecture rtl--------------------------------------------------------------------------------- Error reports assert (tech = virtex2 or tech = virtex4 or tech = lattice) report "Unsupported technology by DDR controller (generic tech)" severity failure; assert (modbanks=1 or modbanks=2) report "Only 1 or 2 module banks is supported (generic modbanks)" severity failure; assert (chipbits=4 or chipbits=8 or chipbits=16) report "DDR chips either have 4, 8 or 16 bits output (generic chipbits)" severity failure; assert (chipsize=64 or chipsize=128 or chipsize=256 or chipsize=512 or chipsize=1024) report "DDR chips either have 64, 128, 256, 512 or 1024 Mbit size" severity failure; assert (buffersize>=2) report "Buffer must have room for at least 2 bursts (generic buffersize)" severity failure; assert (plldelay=0 or plldelay=1) report "Invalid setting for DDRRAM PLL delay (generic plldelay)" severity failure; assert (numahb=1 or numahb=2) report "Only one or two AHB interfaces can be used (generic numahb)" severity failure;--------------------------------------------------------------------------------- APB control -- Controls APB bus. Contains the DDRCFG register. Clear memcmd -- bits when a memory command requested on APB is complete. apbcomb : process(apbr, apbsi, fromMain2APB, rst) variable v : apb_reg_type; begin v:= apbr; if rst = '0' then -- Reset v.ddrcfg_reg := ddrcfg_reset; elsif fromMain2APB.apb_cmd_done = '1' then -- Clear memcmd bits v.ddrcfg_reg(28 downto 27) := "00"; elsif (apbsi.psel(pindex) and apbsi.penable and apbsi.pwrite) = '1' then -- Write v.ddrcfg_reg := apbsi.pwdata(31 downto 1) & fromMain2APB.ready; else v.ddrcfg_reg(0) := fromMain2APB.ready; end if; apbri <= v; fromAPB.ddrcfg_reg <= v.ddrcfg_reg; end process apbcomb; apbclk : process(pclk) begin if rising_edge(pclk) then apbr <= apbri; end if; end process; apbso.prdata <= fromAPB.ddrcfg_reg; apbso.pirq <= (others => '0'); apbso.pindex <= pindex; apbso.pconfig <= pconfig; ------------------------------------------------------------------------------- -- Main controller------------------------------------------------------------------------------- maincomb : process(mainr, fromAHB, fromAHB2Main, fromAPB2Main, rst, fromHS) variable v : main_reg_type; begin v := mainr; v.loadcmdbuffer := '0'; -- Clear Cmd loading bit------------------------------------------------------------------------------- -- DDRCFG control -- Reads DDRCFG from APB controller. Handles refresh command from refresh -- timer and memoory comand requested on APB. case v.apbstate is when idle => v.apb_cmd_done := '0'; -- Refresh timer signals refresh if v.doRefresh = '1' and v.ddrcfg.refresh = '1' then v.apbstate := refresh; -- LMR cmd on APB bus elsif fromAPB2Main.ddrcfg_reg(28 downto 27) = "11" then v.lockAHB := "11"; v.apbstate := wait_lmr1; -- Refresh or Precharge cmd on APB BUS elsif fromAPB2Main.ddrcfg_reg(28 downto 27) > "00" then v.apbstate := cmd; -- Nothing to be done else v.ddrcfg.memcmd := "00"; end if; -- Refresh from Timer when refresh => if v.mainstate = idle then v.ddrcfg.memcmd := "10"; end if; if v.dorefresh = '0' then v.ddrcfg.memcmd := "00"; v.apbstate := idle; end if; -- Refresh or Precharge from APB BUS when cmd => if v.mainstate = idle then v.ddrcfg.memcmd := fromAPB2Main.ddrcfg_reg(28 downto 27); end if; v.apbstate := cmdDone; -- Wait until no more cmd can arrive from AHB ctrl when wait_lmr1 => v.apbstate := wait_lmr2; when wait_lmr2 => v.apbstate := cmdlmr; when cmdlmr => -- Check that no new R/W cmd is to be performed if fromAHB2Main(0).rw_cmd_valid = v.rw_cmd_done(0) and fromAHB2Main(1).rw_cmd_valid = v.rw_cmd_done(1) and v.mainstate = idle then v.ddrcfg.memcmd := "11"; v.ddrcfg.cas := fromAPB2Main.ddrcfg_reg(30 downto 29); v.ddrcfg.bl := fromAPB2Main.ddrcfg_reg(26 downto 25); v.apbstate := cmdDone; end if; when cmdDone => v.lockAHB := "00"; if v.memCmdDone = '1' then v.ddrcfg.memcmd := "00"; v.apb_cmd_done := '1'; v.apbstate := cmdDone2; end if; when cmdDone2 => if fromAPB2Main.ddrcfg_reg(28 downto 27) = "00" then v.apb_cmd_done := '0'; v.apbstate := idle; end if; end case; if v.mainstate = idle then v.ddrcfg.refresh := fromAPB2Main.ddrcfg_reg(31); v.ddrcfg.autopre := fromAPB2Main.ddrcfg_reg(24); v.ddrcfg.r_predict := fromAPB2Main.ddrcfg_reg(23 downto 22); v.ddrcfg.w_prot := fromAPB2Main.ddrcfg_reg(21 downto 20); v.ddrcfg.ready := fromAPB2Main.ddrcfg_reg(0); end if; ------------------------------------------------------------------------------- -- Calcualtes burst length case v.ddrcfg.bl is when "00" => v.burstlength := 2; when "01" => v.burstlength := 4; when "10" => v.burstlength := 8; when others => v.burstlength := 8; end case; ------------------------------------------------------------------------------- -- Calculates row and column address v.tmpcoladdress := (others => (others => '0')); v.rowaddress := (others => (others => '0')); v.coladdress := (others => (others => '0')); v.tmpcolbits := 0; v.colbits := 0; v.rowbits := 0; -- Based on the size of the chip its organization can be calculated case chipsize is when 64 => v.tmpcolbits := 10; v.rowbits := 12; v.refreshTime := DELAY_15600NS; v.maxRefreshTime := DELAY_7_15600NS; -- 64Mbit when 128 => v.tmpcolbits := 11; v.rowbits := 12; v.refreshTime := DELAY_15600NS; v.maxRefreshTime := DELAY_7_15600NS; -- 128Mbit when 256 => v.tmpcolbits := 11; v.rowbits := 13; v.refreshTime := DELAY_7800NS; v.maxRefreshTime := DELAY_7_7800NS; -- 256Mbit when 512 => v.tmpcolbits := 12; v.rowbits := 13; v.refreshTime := DELAY_7800NS; v.maxRefreshTime := DELAY_7_7800NS; -- 512Mbit when 1024 => v.tmpcolbits := 12; v.rowbits := 14; v.refreshTime := DELAY_7800NS; v.maxRefreshTime := DELAY_7_7800NS; -- 1Gbit when others => v.tmpcolbits := 10; v.rowbits := 12; v.refreshTime := DELAY_7800NS; v.maxRefreshTime := DELAY_7_7800NS; -- Others 64Mbit end case; case chipbits is when 4 => v.colbits := v.tmpcolbits; -- x4 bits when 8 => v.colbits := (v.tmpcolbits-1); -- x8 bits when 16 => v.colbits := (v.tmpcolbits-2); -- x16 bits when others => null; end case; v.addressrange := v.colbits + v.rowbits; -- AHB controller 1 -- for i in 0 to ahbadr loop if (i < v.colbits) then v.tmpcoladdress(0)(i) := fromAHB(0).asramso.dataout(i); end if; if (i < (v.addressrange) and i >= v.colbits) then v.rowaddress(0)(i-v.colbits) := fromAHB(0).asramso.dataout(i); end if; if (i < (v.addressrange+2) and i >= v.addressrange) then v.intbankbits(0)(i - v.addressrange) := fromAHB(0).asramso.dataout(i); end if; end loop; -- Inserts bank address and auto precharge bit as A10 v.coladdress(0)(adrbits-1 downto 0) := v.intbankbits(0) & v.tmpcoladdress(0)(12 downto 10) & -- Bit 13 to 11 v.ddrcfg.autopre & -- Bit 10 v.tmpcoladdress(0)(9 downto 0); --Bit 9 to 0 v.rowaddress(0)(adrbits-1 downto (adrbits-2)) := v.intbankbits(0); -- Calculate total numer of useable address bits if modbanks = 2 then -- Calculate memory module bank (CS signals)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -