📄 ddrsp64a.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: ddrsp64a-- File: ddrsp64a.vhd-- Author: Jiri Gaisler - Gaisler Research-- Description: 64-bit DDR266 memory controller with asych AHB 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;entity ddrsp64a is generic ( memtech : integer := 0; hindex : integer := 0; haddr : integer := 0; hmask : integer := 16#f00#; ioaddr : integer := 16#000#; iomask : integer := 16#fff#; MHz : integer := 100; col : integer := 9; Mbyte : integer := 8; fast : integer := 0; pwron : integer := 0; oepol : integer := 0 ); port ( rst : in std_ulogic; clk_ddr : in std_ulogic; clk_ahb : in std_ulogic; ahbsi : in ahb_slv_in_type; ahbso : out ahb_slv_out_type; sdi : in sdctrl_in_type; sdo : out sdctrl_out_type );end; architecture rtl of ddrsp64a isconstant REVISION : integer := 0;constant CMD_PRE : std_logic_vector(2 downto 0) := "010";constant CMD_REF : std_logic_vector(2 downto 0) := "100";constant CMD_LMR : std_logic_vector(2 downto 0) := "110";constant CMD_EMR : std_logic_vector(2 downto 0) := "111";constant abuf : integer := 6;constant hconfig : ahb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_DDRSP, 0, REVISION, 0), 4 => ahb_membar(haddr, '1', '1', hmask), 5 => ahb_iobar(ioaddr, iomask), others => zero32);type mcycletype is (midle, active, ext, leadout);type ahb_state_type is (midle, rhold, dread, dwrite, whold1, whold2);type sdcycletype is (act1, act2, act3, rd1, rd2, rd3, rd4, rd5, rd6, rd7, rd8, wr1, wr2, wr3, wr4a, wr4, wr5, sidle, ioreg1, ioreg2);type icycletype is (iidle, pre, ref1, ref2, emode, lmode, finish);-- sdram configuration registertype sdram_cfg_type is record command : std_logic_vector(2 downto 0); csize : std_logic_vector(1 downto 0); bsize : std_logic_vector(2 downto 0); trcd : std_ulogic; -- tCD : 2/3 clock cycles trfc : std_logic_vector(2 downto 0); trp : std_ulogic; -- precharge to activate: 2/3 clock cycles refresh : std_logic_vector(11 downto 0); renable : std_ulogic; dllrst : std_ulogic; refon : std_ulogic; cke : std_ulogic;end record;type access_param is record haddr : std_logic_vector(31 downto 0); size : std_logic_vector(1 downto 0); hwrite : std_ulogic; hio : std_ulogic;end record;-- local registerstype ahb_reg_type is record hready : std_ulogic; hsel : std_ulogic; hio : std_ulogic; startsd : std_ulogic; ready : std_ulogic; ready2 : std_ulogic; write : std_logic_vector(3 downto 0); state : ahb_state_type; haddr : std_logic_vector(31 downto 0); hrdata : std_logic_vector(31 downto 0); hwdata : std_logic_vector(31 downto 0); hwrite : std_ulogic; htrans : std_logic_vector(1 downto 0); hresp : std_logic_vector(1 downto 0); raddr : std_logic_vector(abuf-1 downto 0); size : std_logic_vector(1 downto 0); acc : access_param;end record;type ddr_reg_type is record startsd : std_ulogic; startsdold : std_ulogic; burst : std_ulogic; hready : std_ulogic; bdrive : std_ulogic; qdrive : std_ulogic; nbdrive : std_ulogic; mstate : mcycletype; sdstate : sdcycletype; cmstate : mcycletype; istate : icycletype; trfc : std_logic_vector(2 downto 0); refresh : std_logic_vector(11 downto 0); sdcsn : std_logic_vector(1 downto 0); sdwen : std_ulogic; rasn : std_ulogic; casn : std_ulogic; dqm : std_logic_vector(15 downto 0); address : std_logic_vector(15 downto 2); -- memory address ba : std_logic_vector( 1 downto 0); waddr : std_logic_vector(abuf-1 downto 0); cfg : sdram_cfg_type; hrdata : std_logic_vector(127 downto 0);end record;signal vcc : std_ulogic;signal r, ri : ddr_reg_type;signal ra, rai : ahb_reg_type;signal rbdrive, ribdrive : std_logic_vector(31 downto 0);signal rdata, wdata : std_logic_vector(127 downto 0);attribute syn_preserve : boolean;attribute syn_preserve of rbdrive : signal is true; begin vcc <= '1'; ahb_ctrl : process(rst, ahbsi, r, ra, rdata) variable v : ahb_reg_type; -- local variables for registers variable startsd : std_ulogic; variable dout : std_logic_vector(31 downto 0); begin v := ra; v.hresp := HRESP_OKAY; v.write := "0000"; case ra.raddr(1 downto 0) is when "00" => v.hrdata := rdata(127 downto 96); when "01" => v.hrdata := rdata(95 downto 64); when "10" => v.hrdata := rdata(63 downto 32); when others => v.hrdata := rdata(31 downto 0); end case; v.ready := not (ra.startsd xor r.startsdold); v.ready2 := ra.ready; if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then v.htrans := ahbsi.htrans; v.haddr := ahbsi.haddr; v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite; if ahbsi.htrans(1) = '1' then v.hio := ahbsi.hmbsel(1); v.hsel := '1'; v.hready := '0'; end if; end if; if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;-- if (ra.hsel and ra.hio and not ra.hready) = '1' then v.hready := '1'; end if; case ra.state is when midle => if ((v.hsel and v.htrans(1)) = '1') then if v.hwrite = '0' then v.state := rhold; v.startsd := not ra.startsd; else v.state := dwrite; v.hready := '1'; -- v.write(0) := not v.haddr(2); v.write(1) := v.haddr(2); v.write := decode(v.haddr(3 downto 2)); end if; end if; v.raddr := ra.haddr(7 downto 2); v.ready := '0'; v.ready2 := '0';-- if not ((ra.hsel and ra.htrans(1) and not ra.htrans(0)) = '1') then if ahbsi.hready = '1' then v.acc := (v.haddr, v.size, v.hwrite, v.hio); end if; when rhold => v.raddr := ra.haddr(7 downto 2); if ra.ready2 = '1' then v.state := dread; v.hready := '1'; v.raddr := ra.raddr + 1; end if; when dread => v.raddr := ra.raddr + 1; v.hready := '1'; if ((v.hsel and v.htrans(1) and v.htrans(0)) = '0') or (ra.raddr(2 downto 0) = "000") then v.state := midle; v.hready := '0'; end if; v.acc := (v.haddr, v.size, v.hwrite, v.hio); when dwrite => v.raddr := ra.haddr(7 downto 2); v.hready := '1';-- v.write(0) := not v.haddr(2); v.write(1) := v.haddr(2); v.write := decode(v.haddr(3 downto 2)); if ((v.hsel and v.htrans(1) and v.htrans(0)) = '0') or (ra.haddr(4 downto 2) = "111") then v.startsd := not ra.startsd; v.state := whold1; v.write := "0000"; v.hready := '0'; end if; when whold1 => v.state := whold2; v.ready := '0'; when whold2 => if ra.ready = '1' then v.state := midle; v.acc := (v.haddr, v.size, v.hwrite, v.hio); end if; end case; v.hwdata := ahbsi.hwdata; if (ahbsi.hready and ahbsi.hsel(hindex) ) = '1' then if ahbsi.htrans(1) = '0' then v.hready := '1'; end if; end if; dout := ra.hrdata(31 downto 0); if rst = '0' then v.hsel := '0'; v.hready := '1'; v.state := midle; v.startsd := '0'; v.hio := '0'; end if; rai <= v; ahbso.hready <= ra.hready; ahbso.hresp <= ra.hresp; ahbso.hrdata <= dout; ahbso.hcache <= not ra.hio; end process; ddr_ctrl : process(rst, r, ra, sdi, rbdrive, wdata) variable v : ddr_reg_type; -- local variables for registers variable startsd : std_ulogic; variable dqm : std_logic_vector(15 downto 0); variable raddr : std_logic_vector(13 downto 0); variable adec : std_ulogic; variable rams : std_logic_vector(1 downto 0); variable ba : std_logic_vector(1 downto 0); variable haddr : std_logic_vector(31 downto 0); variable hsize : std_logic_vector(1 downto 0); variable hwrite : std_ulogic; variable htrans : std_logic_vector(1 downto 0); variable hready : std_ulogic; variable vbdrive : std_logic_vector(31 downto 0); variable bdrive : std_ulogic; variable writecfg: std_ulogic; variable regsd1 : std_logic_vector(31 downto 0); -- data from registers variable regsd2 : std_logic_vector(31 downto 0); -- data from registers begin-- Variable default settings to avoid latches v := r; v.hready := '0'; writecfg := '0'; vbdrive := rbdrive; v.hrdata := sdi.data; v.qdrive :='0'; regsd1 := (others => '0'); regsd1(31 downto 15) := r.cfg.refon & r.cfg.trp & r.cfg.trfc & r.cfg.trcd & r.cfg.bsize & r.cfg.csize & r.cfg.command & r.cfg.dllrst & r.cfg.renable & r.cfg.cke; regsd1(11 downto 0) := r.cfg.refresh; regsd2 := (others => '0'); regsd2(8 downto 0) := conv_std_logic_vector(MHz, 9); regsd2(14 downto 12) := conv_std_logic_vector(3, 3);-- generate DQM from address and write size case ra.acc.size is when "00" => case ra.acc.haddr(3 downto 0) is when "0000" => dqm := "0111111111111111"; when "0001" => dqm := "1011111111111111"; when "0010" => dqm := "1101111111111111"; when "0011" => dqm := "1110111111111111"; when "0100" => dqm := "1111011111111111"; when "0101" => dqm := "1111101111111111"; when "0110" => dqm := "1111110111111111"; when "0111" => dqm := "1111111011111111"; when "1000" => dqm := "1111111101111111"; when "1001" => dqm := "1111111110111111"; when "1010" => dqm := "1111111111011111"; when "1011" => dqm := "1111111111101111"; when "1100" => dqm := "1111111111110111"; when "1101" => dqm := "1111111111111011"; when "1110" => dqm := "1111111111111101"; when others => dqm := "1111111111111110"; end case; when "01" => case ra.acc.haddr(3 downto 1) is when "000" => dqm := "0011111111111111"; when "001" => dqm := "1100111111111111"; when "010" => dqm := "1111001111111111"; when "011" => dqm := "1111110011111111"; when "100" => dqm := "1111111100111111"; when "101" => dqm := "1111111111001111"; when "110" => dqm := "1111111111110011"; when others => dqm := "1111111111111100"; end case; when others => dqm := "0000000000000000"; end case; v.startsd := ra.startsd;-- main FSM case r.mstate is when midle => if r.startsd = '1' then if (r.sdstate = sidle) and (r.cfg.command = "000") and (r.cmstate = midle) then startsd := '1'; v.mstate := active; end if; end if; when others => null; end case; startsd := r.startsd xor r.startsdold;-- generate row and column address size haddr := ra.acc.haddr; haddr(31 downto 20) := haddr(31 downto 20) and not conv_std_logic_vector(hmask, 12); case r.cfg.csize is when "00" => raddr := haddr(25 downto 12); when "01" => raddr := haddr(26 downto 13); when "10" => raddr := haddr(27 downto 14); when others => raddr := haddr(28 downto 15); end case;-- generate bank address ba := genmux(r.cfg.bsize, haddr(29 downto 22)) & genmux(r.cfg.bsize, haddr(28 downto 21));-- generate chip select adec := genmux(r.cfg.bsize, haddr(30 downto 23)); rams := adec & not adec;-- sdram access FSM if r.trfc /= "000" then v.trfc := r.trfc - 1; end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -