⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mctrl.vhd

📁 一个航天航空用的Sparc处理器(配美国欧洲宇航局用的R_tems嵌入式操作系统)的VHDL源代码
💻 VHD
📖 第 1 页 / 共 3 页
字号:
    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 + -