📄 mctrl.vhd
字号:
when others => burst := '0';
end case;
-- Bus request FSM
case r.busstate is
when idle =>
if r.bstate = idle then
if ((mcmi.req and DMAEN) = '1') then
v.busstate := busy; start := '1'; v.master := dma;
v.address := mcmi.address; v.ba := mcmi.address(1 downto 0);
v.read := mcmi.read; v.size := mcmi.size; v.asi := mcmi.asi(3 downto 0);
v.writedata := mcmi.data;
elsif (mcdi.req and not r.pwd) = '1' then
v.busstate := busy; start := '1'; v.master := data;
v.address := mcdi.address; v.ba := mcdi.address(1 downto 0);
v.read := mcdi.read; v.size := mcdi.size; v.asi := mcdi.asi(3 downto 0);
v.writedata := mcdi.data;
elsif mcii.req = '1' then
v.busstate := busy; start := '1'; v.master := inst;
v.address := mcii.address; v.ba := mcii.address(1 downto 0);
v.read := '1'; v.size := "10";
if mcii.su = '1' then v.asi := ASI_SINST;
else v.asi := ASI_UINST;
end if;
end if;
end if;
when bw1 => -- byte write, read full word
if r.ready = '1' then
v.busstate := bw2;
end if;
when bw2 => -- insert the correct byte(s) during partial write
if r.bstate = idle then
start := '1'; v.busstate := busy; v.read := '0'; v.address := r.address2;
end if;
when busy =>
if (r.ready and (r.mexc or not burst)) = '1' then
v.busstate := idle;
end if;
if (r.ready and (not r.read) and burst) = '1' then
if (r.master = dma) and (DMAEN = '1') then
v.writedata := mcmi.data;
else
v.writedata := mcdi.data;
end if;
end if;
when others => null;
end case;
-- decode ASI
if v.asi = ASI_PCI then
v.area := pci;
else
case v.address(31 downto 28) is
when "0000" | "0001" => v.area := rom;
when "0010" | "0011" => v.area := io;
when "0100" | "0101" | "0110" | "0111" => v.area := ram;
when "1000" => v.area := regs;
when others => v.area := pci;
end case;
end if;
-- decode area parameters
leadin := '-'; leadout := '-'; rws := "----"; wws := "----"; adec := "--";
case v.area is
when rom => rws := r.mcfg1.romrws; wws := r.mcfg1.romrws;
leadin := r.mcfg1.romleadin; leadout := r.mcfg1.romleadout;
adec := genmux(r.mcfg1.rombanksz, v.address(29 downto 14)) &
genmux(r.mcfg1.rombanksz, v.address(28 downto 13));
when ram => rws := "00" & r.mcfg2.ramrws; wws := "00" & r.mcfg2.ramrws;
leadin := r.mcfg2.ramleadin; leadout := r.mcfg2.ramleadout;
adec := genmux(r.mcfg2.rambanksz, v.address(29 downto 14)) &
genmux(r.mcfg2.rambanksz, v.address(28 downto 13));
when io => rws := r.mcfg1.iows; wws := r.mcfg1.iows;
leadin := r.mcfg1.ioleadin; leadout := r.mcfg1.ioleadout;
ready := (not r.brdyn) or not r.mcfg1.iordy;
when others => null;
end case;
-- write protection
wprothit := '0'; wprothit1 := '0'; wprothit2 := '0';
if WPROTEN then
aprot := (v.address(29 downto 15) xor wpr.wprot1.addr) and wpr.wprot1.mask;
if (aprot = "000000000000000") then wprothit1 := '1'; end if;
aprot := (v.address(29 downto 15) xor wpr.wprot2.addr) and wpr.wprot2.mask;
if (aprot = "000000000000000") then wprothit2 := '1'; end if;
if (r.busstate = idle) and (start = '1') and ((v.read or v.asi(2)) = '0') then
wprothit :=
((wpr.wprot1.enable and (not wprothit1) and (not wpr.wprot1.ablock)) or
(wpr.wprot2.enable and (not wprothit2) and (not wpr.wprot2.ablock))) or
(((wpr.wprot1.enable and wprothit1 and wpr.wprot1.ablock) or
(wpr.wprot2.enable and wprothit2 and wpr.wprot2.ablock)) and not
((wpr.wprot1.enable and wprothit1 and (not wpr.wprot1.ablock)) or
(wpr.wprot2.enable and wprothit2 and (not wpr.wprot2.ablock))));
end if;
end if;
-- cache freeze operation
if (r.cctrl.ifrz and syso.intack and r.cctrl.ics(0)) = '1' then
v.cctrl.ics := "01";
end if;
if (r.cctrl.dfrz and syso.intack and r.cctrl.dcs(0)) = '1' then
v.cctrl.dcs := "01";
end if;
-- exception detection
if v.read = '1' then wsnew := rws; else wsnew := wws; end if;
if start = '1' then
case v.area is
when rom =>
if (v.read = '0') and (r.mcfg1.romwrite = '0') then
v.mexc := '1';
start := '0'; v.ready := '1';
if ((v.read = '0') and (r.mcfg1.romwrite = '0')) then
v.werr := '1';
end if;
end if;
when ram =>
if (wprothit = '1') then
v.mexc := '1'; start := '0'; v.ready := '1'; v.werr := wprothit;
end if;
when io =>
if (r.mcfg1.ioen = '0') then
v.mexc := '1';
start := '0'; v.ready := '1';
end if;
when regs => null;
when others =>
v.mexc := '1';
start := '0'; v.ready := '1';
end case;
end if;
-- decode access type
case v.area is
when rom =>
if r.mcfg1.romwidth /= "11" then
mem16 := '1';
end if;
if start = '1' then
startmem := '1';
end if;
when ram =>
if r.mcfg2.ramwidth /= "11" then
mem16 := '1';
end if;
if start = '1' then
startmem := '1';
if (r.busstate = idle) and (((not v.read) and (not v.size(1))) = '1')
then
v.busstate := bw1; v.read := '1';
end if;
end if;
when io =>
startmem := start;
when regs =>
startregs := start;
when others => null; -- for now ..
end case;
if (start and mem16) = '1' then v.address(1 downto 0) := "00"; end if;
-- save read data during 8/16 bit reads
if r.ld8 = '1' then
v.readdata := r.readdata(23 downto 0) & r.data(31 downto 24);
end if;
-- generate top address bits for edac checksum (8/16 bit bus only)
case r.area is
when rom => banksz := r.mcfg1.rombanksz;
when ram => banksz := r.mcfg2.rambanksz;
when others => banksz := (others => '-');
end case;
chkaddr := (others => '0');
chkaddr(26 downto 11) := decode(banksz);
chkaddr := r.address(31 downto 28) &
((chkaddr(26 downto 11) & '0') or ('0' & chkaddr(26 downto 11)) or r.address(29 downto 13))
& r.address(12 downto 2);
-- Ram, rom, IO access FSM
case r.bstate is
when idle =>
v.ws := wsnew;
v.address2 := v.address(31 downto 2) & "00";
if (startmem = '1') then
if ((r.busstate = bw2) and ((r.checkedac and edata.merror) = '1')) then
v.ready := '1';
else
if leadin = '1' then v.bstate := ldin;
else
csen := '1';
if v.read = '1' then
if (mem16 = '0') then
if (v.ws = "0000") then v.ready := '1'; end if;
end if;
v.bstate := main;
else
v.bstate := bwrite; v.wren := '1'; bdrive := '1';
end if;
end if;
end if;
end if;
when ldin =>
if v.read = '1' then
v.bstate := main;
if (mem16 = '0') then
if (v.ws = "0000") then v.ready := '1'; end if;
end if;
else
v.bstate := bwrite; v.wren := '1'; bdrive := '1';
end if;
csen := '1';
when main =>
csen := '1'; v.wren := not v.read; bdrive := not v.read;
case busw is
when "00" =>
if r.ajam = '0' then
v.address2(9 downto 2) := r.address(9 downto 2);
end if;
if ((r.ws = "0001") and (r.ajam = '1')) or
((r.ws = "0000") and (r.address(1 downto 0) = "10") and (wsnew = "0000") and (r.checkedac = '0')) or
((r.ws = "0001") and (r.address(1 downto 0) = "11") and (r.checkedac = '0'))
then v.ready := '1'; end if;
if r.ws = "0001" then v.wren := '0'; end if;
if r.ws = "0000" then
v.ld8 := r.read and not r.ajam; v.ws := wsnew; v.wren := '0';
if r.ready = '1'
then
v.ajam := '0';
if burst = '1' then
v.address(31 downto 10) := r.address2(31 downto 10);
v.address(9 downto 2) := r.address2(9 downto 2) + 1;
v.address(1 downto 0) := "00";
if v.read = '0' then
v.bstate := bwrite; bdrive := '1'; v.wren := '1'; v.ready := '0';
end if;
else
if leadout = '1' then v.bstate := ldout;
else v.read := '1'; v.bstate := idle; end if;
csen := '0'; bdrive := '0';
end if;
v.ready := not r.ready;
else
v.address(1 downto 0) := r.address(1 downto 0) + 1;
if v.read = '0' then
v.bstate := bwrite; bdrive := '1'; v.wren := '1'; v.ready := '0';
v.writedata := v.writedata(23 downto 0) & '0' & cbout;
end if;
if (r.ajam = '0') and (r.address(1 downto 0) = "11") and (r.checkedac = '1')
then
v.ajam := '1'; v.address := chkaddr;
if (wsnew = "0000") then v.ready := r.read; end if;
end if;
end if;
else
v.ws := r.ws - 1;
end if;
when others =>
v.address2(9 downto 2) := r.address(9 downto 2);
if (r.ws = "0001") and (ready = '1') then
v.ready := '1'; v.wren := '0';
end if;
if r.ws = "0000" then
if r.ready = '0' then v.ready := ready; end if;
if r.ready = '1' then
v.wren := '0';
if burst = '1' then
v.address(9 downto 2) := v.address(9 downto 2) + 1;
v.ws := wsnew;
if wsnew = "0000" then
v.ready := '1';
end if;
if v.read = '0' then
v.bstate := bwrite; bdrive := '1'; v.wren := '1';
v.ready := '0';
end if;
else
if leadout = '1' then v.bstate := ldout;
else v.read := '1'; v.bstate := idle; end if;
csen := '0'; bdrive := '0';
end if;
end if;
else
v.ws := r.ws - 1;
end if;
end case;
when bwrite =>
bdrive := '1'; v.bstate := main; csen := '1';
if r.ws = "0000" then
v.wren := '0';
if (busw /= "00") or (r.ajam = '1') or
((busw = "00") and (r.address(1 downto 0) = "11") and (r.checkedac = '0'))
then v.ready := ready; end if;
else
v.wren := '1';
end if;
when ldout =>
v.bstate := idle; v.read := '1';
when others => null;
end case;
-- Register access FSM
case r.rstate is
when idle =>
if startregs = '1' then
v.ready := v.read;
if v.address(7 downto 6) = "00" then
v.rstate := lregs;
else
v.rstate := eregs;
end if;
end if;
when lregs =>
case r.address(5 downto 2) is
when "0000" =>
regsd(28 downto 0) := r.mcfg1.iowidth &
r.mcfg1.iordy & r.mcfg1.ioleadout &
r.mcfg1.ioleadin & r.mcfg1.iows & r.mcfg1.ioen &
r.mcfg1.extlatch &
r.mcfg1.rombanksz & r.mcfg1.romleadout &
r.mcfg1.romleadin & r.mcfg1.romwrite & r.mcfg1.romedac &
r.mcfg1.romwidth & r.mcfg1.romwws & r.mcfg1.romrws;
when "0001" =>
regsd(12 downto 0) := r.mcfg2.rambanksz &
r.mcfg2.ramleadout & r.mcfg2.ramleadin & r.mcfg2.ramedac &
r.mcfg2.ramwidth & r.mcfg2.ramwws & r.mcfg2.ramrws;
when "0010" =>
regsd(7 downto 0) := r.edacctrl.wbypass & r.edacctrl.wcheckbits;
when "0011" => regsd := r.failaddr;
when "0100" =>
regsd := "000000000000000000000" & r.memstat.lock &
r.memstat.mulerr & r.memstat.newerr &
r.memstat.read & r.memstat.asi & r.memstat.errtype;
when "0101" =>
regsd(16 downto 0) := r.cctrl.ib & mcii.flush &
mcdi.flush & r.cctrl.ite & r.cctrl.ide &
r.cctrl.dte & r.cctrl.dde & r.cctrl.dfrz &
r.cctrl.ifrz & r.cctrl.dcs & r.cctrl.ics;
when "0111" =>
if WPROTEN then
regsd := wpr.wprot1.enable & wpr.wprot1.ablock &
wpr.wprot1.addr & wpr.wprot1.mask;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -