📄 sdctrl.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: sdctrl-- File: sdctrl.vhd-- Author: Jiri Gaisler - Gaisler Research-- Description: 32-bit SDRAM memory controller.------------------------------------------------------------------------------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;entity sdctrl is generic ( hindex : integer := 0; haddr : integer := 0; hmask : integer := 16#f00#; ioaddr : integer := 16#000#; iomask : integer := 16#fff#; wprot : integer := 0; invclk : integer := 0; fast : integer := 0; pwron : integer := 0; sdbits : integer := 32; oepol : integer := 0; pageburst : integer := 0 ); port ( rst : in std_ulogic; clk : 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 sdctrl isconstant WPROTEN : boolean := wprot = 1;constant SDINVCLK : boolean := invclk = 1;constant BUS64 : boolean := (sdbits = 64);constant REVISION : integer := 1;constant hconfig : ahb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_SDCTRL, 0, REVISION, 0), 4 => ahb_membar(haddr, '1', '1', hmask), 5 => ahb_iobar(ioaddr, iomask), others => zero32);type mcycletype is (midle, active, leadout);type sdcycletype is (act1, act2, act3, rd1, rd2, rd3, rd4, rd5, rd6, rd7, rd8, wr1, wr2, wr3, wr4, wr5, sidle);type icycletype is (iidle, pre, ref, lmode, finish);-- sdram configuration registertype sdram_cfg_type is record command : std_logic_vector(1 downto 0); csize : std_logic_vector(1 downto 0); bsize : std_logic_vector(2 downto 0); casdel : std_ulogic; -- CAS to data delay: 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(14 downto 0); renable : std_ulogic; pageburst : std_ulogic;end record;-- local registerstype reg_type is record hready : std_ulogic; hsel : std_ulogic; bdrive : std_ulogic; nbdrive : std_ulogic; burst : std_ulogic; wprothit : std_ulogic; hio : std_ulogic; startsd : std_ulogic; mstate : mcycletype; sdstate : sdcycletype; cmstate : mcycletype; istate : icycletype; icnt : std_logic_vector(2 downto 0); haddr : std_logic_vector(31 downto 0); hrdata : std_logic_vector(sdbits-1 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); size : std_logic_vector(1 downto 0); cfg : sdram_cfg_type; trfc : std_logic_vector(2 downto 0); refresh : std_logic_vector(14 downto 0); sdcsn : std_logic_vector(1 downto 0); sdwen : std_ulogic; rasn : std_ulogic; casn : std_ulogic; dqm : std_logic_vector(7 downto 0); address : std_logic_vector(16 downto 2); -- memory address bsel : std_ulogic;end record;signal r, ri : reg_type;signal rbdrive, ribdrive : std_logic_vector(31 downto 0);attribute syn_preserve : boolean;attribute syn_preserve of rbdrive : signal is true; begin ctrl : process(rst, ahbsi, r, sdi, rbdrive) variable v : reg_type; -- local variables for registers variable startsd : std_ulogic; variable dataout : std_logic_vector(31 downto 0); -- data from memory variable regsd : std_logic_vector(31 downto 0); -- data from registers variable dqm : std_logic_vector(7 downto 0); variable raddr : std_logic_vector(12 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 dout : 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 lline : std_logic_vector(2 downto 0); variable lineburst : boolean; begin-- Variable default settings to avoid latches v := r; startsd := '0'; v.hresp := HRESP_OKAY; vbdrive := rbdrive; v.hrdata(sdbits-1 downto sdbits-32) := sdi.data(sdbits-1 downto sdbits-32); v.hrdata(31 downto 0) := sdi.data(31 downto 0); v.hwdata := ahbsi.hwdata; lline := not r.cfg.casdel & r.cfg.casdel & r.cfg.casdel; if (pageburst = 0) or ((pageburst = 2) and r.cfg.pageburst = '0') then lineburst := true; else lineburst := false; end if; if ((ahbsi.hready and ahbsi.hsel(hindex)) = '1') then v.size := ahbsi.hsize(1 downto 0); v.hwrite := ahbsi.hwrite; v.htrans := ahbsi.htrans; if ahbsi.htrans(1) = '1' then v.hio := ahbsi.hmbsel(1); v.hsel := '1'; v.hready := v.hio; end if; v.haddr := ahbsi.haddr; end if; if (r.hsel = '1') and (ahbsi.hready = '0') then haddr := r.haddr; hsize := r.size; htrans := r.htrans; hwrite := r.hwrite; else haddr := ahbsi.haddr; hsize := ahbsi.hsize(1 downto 0); htrans := ahbsi.htrans; hwrite := ahbsi.hwrite; end if; if fast = 1 then haddr := r.haddr; end if; if ahbsi.hready = '1' then v.hsel := ahbsi.hsel(hindex); end if;-- main state case r.size is when "00" => case r.haddr(1 downto 0) is when "00" => dqm := "11110111"; when "01" => dqm := "11111011"; when "10" => dqm := "11111101"; when others => dqm := "11111110"; end case; when "01" => if r.haddr(1) = '0' then dqm := "11110011"; else dqm := "11111100"; end if; when others => dqm := "11110000"; end case; if BUS64 and (r.bsel = '1') then dqm := dqm(3 downto 0) & "1111"; end if;-- main FSM case r.mstate is when midle => if ((v.hsel and htrans(1) and not v.hio) = '1') then if (r.sdstate = sidle) and (r.cfg.command = "00") and (r.cmstate = midle) and (v.hio = '0') then if fast = 0 then startsd := '1'; else v.startsd := '1'; end if; v.mstate := active; end if; end if; when others => null; end case; startsd := startsd or r.startsd;-- generate row and column address size case r.cfg.csize is when "00" => raddr := haddr(22 downto 10); when "01" => raddr := haddr(23 downto 11); when "10" => raddr := haddr(24 downto 12); when others => if r.cfg.bsize = "111" then raddr := haddr(26 downto 14); else raddr := haddr(25 downto 13); end if; end case;-- generate bank address ba := genmux(r.cfg.bsize, haddr(28 downto 21)) & genmux(r.cfg.bsize, haddr(27 downto 20));-- generate chip select if BUS64 then adec := genmux(r.cfg.bsize, haddr(30 downto 23)); v.bsel := genmux(r.cfg.bsize, r.haddr(29 downto 22)); else adec := genmux(r.cfg.bsize, haddr(29 downto 22)); v.bsel := '0'; end if; rams := adec & not adec;-- sdram access FSM if r.trfc /= "000" then v.trfc := r.trfc - 1; end if; case r.sdstate is when sidle => if (startsd = '1') and (r.cfg.command = "00") and (r.cmstate = midle) then v.address(16 downto 2) := ba & raddr; v.sdcsn := not rams(1 downto 0); v.rasn := '0'; v.sdstate := act1; v.startsd := '0'; end if; when act1 => v.rasn := '1'; v.trfc := r.cfg.trfc; if r.cfg.casdel = '1' then v.sdstate := act2; else v.sdstate := act3; v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1); end if; if WPROTEN then v.wprothit := sdi.wprot; if sdi.wprot = '1' then v.hresp := HRESP_ERROR; end if; end if; when act2 => v.sdstate := act3; v.hready := r.hwrite and ahbsi.htrans(0) and ahbsi.htrans(1); if WPROTEN and (r.wprothit = '1') then v.hresp := HRESP_ERROR; v.hready := '0'; end if; when act3 => v.casn := '0'; v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2); v.dqm := dqm; v.burst := r.hready; if r.hwrite = '1' then v.sdstate := wr1; v.sdwen := '0'; v.bdrive := '0'; if ahbsi.htrans = "11" or (r.hready = '0') then v.hready := '1'; end if; if WPROTEN and (r.wprothit = '1') then v.hresp := HRESP_ERROR; v.hready := '1'; v.sdstate := wr1; v.sdwen := '1'; v.bdrive := '1'; v.casn := '1'; end if; else v.sdstate := rd1; end if; when wr1 => v.address(14 downto 2) := r.haddr(13 downto 12) & '0' & r.haddr(11 downto 2); if (((r.burst and r.hready) = '1') and (r.htrans = "11")) and not (WPROTEN and (r.wprothit = '1')) then v.hready := ahbsi.htrans(0) and ahbsi.htrans(1) and r.hready; if ((r.haddr(5 downto 2) = "1111") and (r.cfg.command = "10")) then -- exit on refresh v.hready := '0'; end if; else v.sdstate := wr2; v.bdrive := '1'; v.casn := '1'; v.sdwen := '1'; v.dqm := (others => '1'); end if; when wr2 => if (r.cfg.trp = '0') then v.rasn := '0'; v.sdwen := '0'; end if; v.sdstate := wr3; when wr3 =>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -