📄 ddrctrl.vhd
字号:
if fromAHB(0).asramso.dataout(v.addressrange +2) = '0' then v.bankselect(0) := BANK0; else v.bankselect(0) := BANK1; end if; else v.bankselect(0) := BANK0; end if; -- This is for keeping track of which banks has a active row v.pre_bankadr(0):= conv_integer(v.bankselect(0)(0) & v.rowaddress(0)(adrbits-1 downto (adrbits-2))); -- AHB Controller 2 -- for i in 0 to ahbadr loop if (i < v.colbits) then v.tmpcoladdress(1)(i) := fromAHB(1).asramso.dataout(i); end if; if (i < (v.addressrange) and i >= v.colbits) then v.rowaddress(1)(i-v.colbits) := fromAHB(1).asramso.dataout(i); end if; if (i < (v.addressrange+2) and i >= v.addressrange) then v.intbankbits(1)(i - v.addressrange) := fromAHB(1).asramso.dataout(i); end if; end loop; -- Inserts bank address and auto precharge bit as A10 v.coladdress(1)(adrbits-1 downto 0) := v.intbankbits(1) & v.tmpcoladdress(1)(12 downto 10) & -- Bit 13 to 11 v.ddrcfg.autopre & -- Bit 10 v.tmpcoladdress(1)(9 downto 0); --Bit 9 to 0 v.rowaddress(1)(adrbits-1 downto (adrbits-2)) := v.intbankbits(1); -- Calculate total numer of useable address bits if modbanks = 2 then -- Calculate memory module bank (CS signals) if fromAHB(1).asramso.dataout(v.addressrange +2) = '0' then v.bankselect(1) := BANK0; else v.bankselect(1) := BANK1; end if; else v.bankselect(1) := BANK0; end if; -- This is for keeping track of which banks has a active row v.pre_bankadr(1):= conv_integer(v.bankselect(1)(0) & v.rowaddress(1)(adrbits-1 downto (adrbits-2))); -- ((1bit(Lower/upper half if 32 bit mode))) + 1bit(module bank select) + -- 2bits(Chip bank selekt) + Xbits(address, depending on chip size) ------------------------------------------------------------------------------- -- Calculate LMR command address v.lmradr(adrbits-1 downto 7) := (others => '0'); -- CAS value case v.ddrcfg.cas is when "00" => v.lmradr(6 downto 4) := "010"; when "01" => v.lmradr(6 downto 4) := "110"; when "10" => v.lmradr(6 downto 4) := "011"; when others => v.lmradr(6 downto 4) := "010"; end case; -- Burst type, seqencial or interleaved (fixed att seqencial) v.lmradr(3) := '0'; -- Burst length case v.ddrcfg.bl is when "00" => v.lmradr(2 downto 0) := "001"; when "01" => v.lmradr(2 downto 0) := "010"; when "10" => v.lmradr(2 downto 0) := "011"; when others => v.lmradr(2 downto 0) := "010"; end case; ------------------------------------------------------------------------------- -- Auto refresh timer case v.timerstate is when t1 => v.doRefresh := '0'; v.refreshcnt := v.refreshTime; v.timerstate := t2; when t2 => v.doRefresh := '0'; v.refreshcnt := mainr.refreshcnt -1; if v.refreshcnt < 50 then v.timerstate := t3; end if; when t3 => if mainr.refreshcnt > 1 then v.refreshcnt := mainr.refreshcnt -1; end if; v.doRefresh := '1'; if v.refreshDone = '1' then v.refreshcnt := mainr.refreshcnt + v.refreshTime; v.timerstate := t4; end if; when t4 => v.doRefresh := '0'; v.timerstate := t2; when others => null; end case; ------------------------------------------------------------------------------- -- Init statemachine case v.initstate is when idle => v.memInitDone := '0'; if v.doMemInit = '1' then if plldelay = 1 then -- Using refrshtimer for initial wait v.refreshcnt := DELAY_200US +50; v.timerstate := t2; v.initstate := i1; else v.initstate := i2; end if; end if; when i1 => if v.doRefresh = '1' then v.initstate := i2; end if; when i2 => v.cs := "00"; if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_NOP; v.loadcmdbuffer := '1'; v.initstate := i3; end if; when i3 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_PRE; v.loadcmdbuffer := '1'; v.adrbufferdata(10) := '1'; v.initstate := i4; end if; when i4 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_LMR; v.loadcmdbuffer := '1'; v.adrbufferdata(adrbits-1 downto (adrbits-2)) := "01"; v.adrbufferdata((adrbits -3) downto 0) := (others => '0'); v.initstate := i5; end if; when i5 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_LMR; v.loadcmdbuffer := '1'; v.adrbufferdata := v.lmradr; v.refreshcnt := 250; v.timerstate := t2; --200 cycle count v.adrbufferdata(8) := '1'; v.initstate := i6; end if; when i6 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_PRE; v.loadcmdbuffer := '1'; v.adrbufferdata(10) := '1'; v.initstate := i7; end if; when i7 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_AR; v.loadcmdbuffer := '1'; v.initstate := i8; end if; when i8 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_AR; v.loadcmdbuffer := '1'; v.initstate := i9; end if; when i9 => if fromHS.hs_busy = '0' then v.cmdbufferdata := CMD_LMR; v.loadcmdbuffer := '1'; v.adrbufferdata := v.lmradr; v.initstate := i10; end if; when i10 => if v.doRefresh = '1' then v.initstate := i11; end if; when i11 => v.memInitDone := '1'; if v.doMemInit = '0' then v.initstate := idle; end if; when others => null; end case; ------------------------------------------------------------------------------- -- Main controller statemachine case v.mainstate is -- Initialize memory when init => v.doMemInit := '1'; v.ready := '0'; if v.memInitDone = '1' then v.mainstate := idle; end if; -- Await command when idle => v.doMemInit := '0'; v.RefreshDone := '0'; v.memCmdDone := '0'; v.ready := '1'; v.use_bl := mainr.burstlength; v.use_cas := mainr.ddrcfg.cas; if v.ddrcfg.memcmd /= "00" then v.mainstate := c1; elsif fromAHB2Main(0).rw_cmd_valid /= v.rw_cmd_done(0) or fromAHB2Main(1).rw_cmd_valid /= v.rw_cmd_done(1) then -- This code is to add read priority between the ahb controllers -- if fromAHB2Main(0).rw_cmd_valid /= v.rw_cmd_done(0) and-- fromAHB(0).asramso.dataout(ahbadr) = '0' then-- v.use_ahb := 0;-- v.use_buf := v.rw_cmd_done(0)+1;-- elsif fromAHB2Main(1).rw_cmd_valid /= v.rw_cmd_done(1) and-- fromAHB(1).asramso.dataout(ahbadr) = '0' then-- v.use_ahb := 1;-- v.use_buf := v.rw_cmd_done(1)+1; if fromAHB2Main(0).rw_cmd_valid /= v.rw_cmd_done(0) then v.use_ahb := 0; v.use_buf := v.rw_cmd_done(0)+1; else v.use_ahb := 1; v.use_buf := v.rw_cmd_done(1)+1; end if; -- Check if the chip bank which is to be R/W has a row open if mainr.pre_chg(v.pre_bankadr(v.use_ahb)) = '1' then -- Check if the row which is open is the same that will be R/W if mainr.pre_row(v.pre_bankadr(v.use_ahb)) = v.rowaddress(v.use_ahb) then v.mainstate := rw; -- R/W to a different row then the one open, has to precharge and -- activate new row else v.mainstate := pre1; end if; -- No row open, has to activate row else v.mainstate := act1; end if; end if; -- Nothing to do, if 10 idle cycles, run Refreash (if needed) if v.idlecnt = 10 and v.refreshcnt < v.maxRefreshTime then v.doRefresh := '1'; v.idlecnt := 0; v.timerstate := t3; v.refreshcnt := mainr.refreshcnt + v.refreshTime; elsif v.idlecnt = 10 then v.idlecnt := 0; else v.idlecnt := mainr.idlecnt + 1; end if; -- Precharge memory when pre1 => if fromHS.hs_busy = '0' then v.cs := v.bankselect(mainr.use_ahb); -- Select chip bank to precharge v.adrbufferdata := (others => '0'); v.adrbufferdata(adrbits-1 downto (adrbits-2)) := v.rowaddress(mainr.use_ahb)(adrbits-1 downto (adrbits-2)); v.cmdbufferdata := CMD_PRE; -- Clear bit in register for active rows v.pre_chg(v.pre_bankadr(mainr.use_ahb)):= '0'; v.loadcmdbuffer := '1'; v.mainstate := act1; end if; -- Activate row in memory when act1 => -- Get adr and cmd from AHB, set to HS if fromHS.hs_busy = '0' then v.cs := v.bankselect(mainr.use_ahb); v.cmdbufferdata := CMD_ACTIVE; v.adrbufferdata := v.rowaddress(mainr.use_ahb); v.loadcmdbuffer := '1'; -- Set bit in register for active row if auto-precharge is disabled if v.ddrcfg.autopre = '0' then v.pre_chg(v.pre_bankadr(mainr.use_ahb)) := '1'; v.pre_row(v.pre_bankadr(mainr.use_ahb)) := v.rowaddress(mainr.use_ahb); end if; v.mainstate := rw; end if; -- Issu read or write to HS part when rw => if fromAHB(mainr.use_ahb).asramso.dataout(ahbadr) = '1' then v.cmdbufferdata := CMD_WRITE; else v.cmdbufferdata := CMD_READ; end if; if v.ddrcfg.autopre = '1' then v.pre_chg(v.pre_bankadr(mainr.use_ahb)) := '0'; end if; v.adrbufferdata := v.coladdress(mainr.use_ahb); v.cs := v.bankselect(mainr.use_ahb); v.idlecnt := 0; if fromHS.hs_busy = '0' then if fromAHB2Main(mainr.use_ahb).w_data_valid /= v.rw_cmd_done(mainr.use_ahb) then v.loadcmdbuffer := '1'; v.rw_cmd_done(mainr.use_ahb) := v.rw_cmd_done(mainr.use_ahb)+1; v.sync2_adr(mainr.use_ahb) := v.rw_cmd_done(mainr.use_ahb)+1; v.mainstate := idle; end if; end if; -- Issue prechare, auto refresh or LMR to HS part when c1 => v.idlecnt := 0; if fromHS.hs_busy = '0' then v.cs := BANK01;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -