📄 smc_mctrl.vhd
字号:
if r.area(io) = '1' then rws := r.mcfg1.iows; wws := r.mcfg1.iows; if r.mcfg1.ioen = '0' then addrerr := '1'; end if; end if;-- generate data buffer enables bdrive := (others => '1'); case r.busw is when "00" => if BUS8EN then bdrive := "0001"; end if; when "01" => if BUS16EN then bdrive := "0011"; end if; when others => end case;-- generate chip select and output enable rams := '0' & decode(adec); case srbanks is when 0 => rams := "00000"; when 1 => rams := "00001"; when 2 => rams := "000" & (rams(3 downto 2) or rams(1 downto 0)); when others => if RAMSEL5 and (haddr(sdrasel) = '1') then rams := "10000"; end if; end case; iosn := '1'; ramsn := (others => '1'); romsn := (others => '1'); if area(rom) = '1' then romsn := (not haddr(romasel)) & haddr(romasel); end if; if area(ram) = '1' then ramsn := not rams; end if; if area(io) = '1' then iosn := '0'; end if;-- generate write strobe wrn := "0000"; case r.busw is when "00" => if BUS8EN then wrn := "1110"; end if; when "01" => if BUS16EN then if (r.size = "00") and (r.brmw = '0') then wrn := "11" & (not r.address(0)) & r.address(0); else wrn := "1100"; end if; end if; when "10" | "11" => case r.size is when "00" => case r.address(1 downto 0) is when "00" => wrn := "1110"; when "01" => wrn := "1101"; when "10" => wrn := "1011"; when others => wrn := "0111"; end case; when "01" => wrn := not r.address(1) & not r.address(1) & r.address(1) & r.address(1); when others => null; end case; when others => null; end case; if (r.mcfg2.rmw = '1') and (r.area(ram) = '1') then wrn := not bdrive; end if; if (((ahbsi.hready and ahbsi.hsel(hindex) and ahbsi.htrans(1)) = '1') or (((sdmo.aload and r.hsel) = '1') and SDRAMEN)) then v.area := area; v.address := haddr; if (busw = "00") and (hwrite = '0') and (area(io) = '0') and BUS8EN then v.address(1 downto 0) := "00"; end if; if (busw = "01") and (hwrite = '0') and (area(io) = '0') and BUS16EN then v.address(1 downto 0) := "00"; end if; if (brmw = '1') then v.read := '1'; else v.read := not hwrite; end if; v.busw := busw; v.brmw := brmw; end if;-- Select read data depending on bus width if BUS8EN and (r.busw = "00") then memdata := r.readdata(23 downto 0) & r.data(31 downto 24); elsif BUS16EN and (r.busw = "01") then memdata := r.readdata(15 downto 0) & r.data(31 downto 16); else memdata := r.data; end if; bwdata := memdata;-- Merge data during byte write writedata := ahbsi.hwdata; if ((r.brmw and r.busw(1)) = '1') then case r.address(1 downto 0) is when "00" => writedata(15 downto 0) := bwdata(15 downto 0); if r.size = "00" then writedata(23 downto 16) := bwdata(23 downto 16); end if; when "01" => writedata(31 downto 24) := bwdata(31 downto 24); writedata(15 downto 0) := bwdata(15 downto 0); when "10" => writedata(31 downto 16) := bwdata(31 downto 16); if r.size = "00" then writedata(7 downto 0) := bwdata(7 downto 0); end if; when others => writedata(31 downto 8) := bwdata(31 downto 8); end case; end if; if (r.brmw = '1') and (r.busw = "01") and BUS16EN then if (r.address(0) = '0') then writedata(23 downto 16) := r.data(23 downto 16); else writedata(31 downto 24) := r.data(31 downto 24); end if; end if;-- save read data during 8/16 bit reads if BUS8EN and (r.ready8 = '1') and (r.busw = "00") then v.readdata := v.readdata(23 downto 0) & r.data(31 downto 24); elsif BUS16EN and (r.ready8 = '1') and (r.busw = "01") then v.readdata := v.readdata(15 downto 0) & r.data(31 downto 16); end if;-- Ram, rom, IO access FSM if r.read = '1' then wsnew := rws; else wsnew := wws; end if; case r.bstate is when idle => v.ws := wsnew; if r.bdrive(0) = '1' then if r.busw(1) = '1' then v.writedata := writedata; else v.writedata(31 downto 16) := writedata(31 downto 16); v.writedata8 := writedata(15 downto 0); end if; end if; if (r.srhsel = '1') and ((sdmo.busy = '0') or not SDRAMEN) then if WPROTEN then wprothitx := wpo.wprothit; end if; if (wprothitx or addrerr) = '1' then v.hresp := HRESP_ERROR; v.bstate := berr; v.bdrive := (others => '1'); elsif r.read = '0' then if (r.busw = "00") and (r.area(io) = '0') and BUS8EN then v.bstate := bwrite8; elsif (r.busw = "01") and (r.area(io) = '0') and BUS16EN then v.bstate := bwrite16; else v.bstate := bwrite; end if; v.wrn := wrn; v.writen := '0'; v.bdrive := not bdrive; else if r.oen = '1' then v.ramoen := r.ramsn; v.oen := '0'; else if (r.busw = "00") and (r.area(io) = '0') and BUS8EN then v.bstate := bread8; elsif (r.busw = "01") and (r.area(io) = '0') and BUS16EN then v.bstate := bread16; else v.bstate := bread; end if; end if; end if; end if; when berr => v.bstate := idle; ready := '1'; v.hresp := HRESP_ERROR; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bdrive := (others => '1'); when bread => if ((r.ws = "0000") and (r.ready = '0') and (bready = '1')) then if r.brmw = '0' then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; end if; if (((ahbsi.hsel(hindex) = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.read := not r.hwrite; if r.brmw = '0' then v.ramsn := (others => '1'); v.romsn := (others => '1'); else v.echeck := '1'; end if; end if; end if; if r.ready = '1' then v.ws := rws; else if r.ws /= "0000" then v.ws := r.ws - 1; end if; end if; when bwrite => if (r.ws = "0000") and (bready = '1') then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '1'); v.bstate := idle; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; when bread8 => if BUS8EN then if (r.ws = "0000") and (r.ready8 = '0') and (bready = '1') then v.ready8 := '1'; v.ws := rws; v.address(1 downto 0) := r.address(1 downto 0) + 1; if (r.address(1 downto 0) = "11") then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; if (((ahbsi.hsel(hindex) = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.ramsn := (others => '1'); v.romsn := (others => '1'); end if; end if; end if; if (r.ready8 = '1') then v.ws := rws; elsif r.ws /= "0000" then v.ws := r.ws - 1; end if; else v.bstate := idle; end if; when bwrite8 => if BUS8EN then if (r.ws = "0000") and (r.ready8 = '0') and (bready = '1') then v.ready8 := '1'; v.wrn := (others => '1'); v.writen := '1'; end if; if (r.ws = "0000") and (bready = '1') and ((r.address(1 downto 0) = "11") or ((r.address(1 downto 0) = "01") and (r.size = "01")) or (r.size = "00")) then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '1'); v.bstate := idle; end if; if (r.ready8 = '1') then v.address(1 downto 0) := r.address(1 downto 0) + 1; v.ws := rws; v.writedata(31 downto 16) := r.writedata(23 downto 16) & r.writedata8(15 downto 8); v.writedata8(15 downto 8) := r.writedata8(7 downto 0); v.bstate := idle; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; else v.bstate := idle; end if; when bread16 => if BUS16EN then if (r.ws = "0000") and (bready = '1') and ((r.address(1) or r.brmw) = '1') and (r.ready8 = '0') then if r.brmw = '0' then ready := '1'; v.address := ahbsi.haddr; v.echeck := '1'; end if; if (((ahbsi.hsel(hindex) = '0') or (ahbsi.htrans /= HTRANS_SEQ)) or (r.hburst = HBURST_SINGLE)) then if r.brmw = '0' then v.ramsn := (others => '1'); v.romsn := (others => '1'); end if; v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bstate := idle; v.read := not r.hwrite; end if; end if; if (r.ws = "0000") and (bready = '1') and (r.ready8 = '0') then v.ready8 := '1'; v.ws := rws; if r.brmw = '0' then v.address(1) := not r.address(1); end if; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; else v.bstate := idle; end if; when bwrite16 => if BUS16EN then if (r.ws = "0000") and (bready = '1') and ((r.address(1 downto 0) = "10") or (r.size(1) = '0')) then ready := '1'; v.wrn := (others => '1'); v.writen := '1'; v.echeck := '1'; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.iosn := "11"; v.bdrive := (others => '1'); v.bstate := idle; end if; if (r.ws = "0000") and (bready = '1') and (r.ready8 = '0') then v.ready8 := '1'; v.wrn := (others => '1'); v.writen := '1'; end if; if (r.ready8 = '1') then v.address(1) := not r.address(1); v.ws := rws; v.writedata(31 downto 16) := r.writedata8(15 downto 0); v.bstate := idle; end if; if r.ws /= "0000" then v.ws := r.ws - 1; end if; else v.bstate := idle; end if; when others => end case;-- if BUSY or IDLE cycle seen, or if de-selected, return to idle state if (ahbsi.hready = '1') then if ((ahbsi.hsel(hindex) = '0') or (ahbsi.htrans = HTRANS_BUSY) or (ahbsi.htrans = HTRANS_IDLE)) then v.bstate := idle; v.ramsn := (others => '1'); v.romsn := (others => '1'); v.ramoen := (others => '1'); v.oen := '1'; v.iosn := "11"; v.bdrive := (others => '1'); v.wrn := (others => '1'); v.writen := '1'; v.hsel := '0'; ready := ahbsi.hsel(hindex); v.srhsel := '0'; elsif srhsel = '1' then v.romsn := romsn; v.ramsn(4 downto 0) := ramsn(4 downto 0); v.iosn := iosn & '1'; if v.read = '1' then v.ramoen(4 downto 0) := ramsn(4 downto 0); v.oen := leadin; end if; end if; end if;-- error checking and reporting noerror := '1'; if ((r.echeck and r.mcfg1.bexcen and not r.bexcn) = '1') then noerror := '0'; v.bstate := berr; v.hresp := HRESP_ERROR; v.bdrive := (others => '1');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -