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

📄 fp1eu.vhd

📁 sparc org, vhdl rtl code
💻 VHD
📖 第 1 页 / 共 2 页
字号:
      rxv.state := rx.state; rxv.csr.tt := rx.csr.tt; 
    end if;
    if ((cpi.flush or cpi.dtrap or cpi.dannul) = '1') then
      ldlock := '0';
    end if;

-------------------------------------------------------------
-- execute stage
-------------------------------------------------------------

    -- generate regfile addresses
    if holdn = '0' then
      op  := cpi.me.inst(31 downto 30);
      rd  := cpi.me.inst(29 downto 25);
      op3 := cpi.me.inst(24 downto 19);
      rs1 := cpi.me.inst(18 downto 14);
      rs2 := cpi.me.inst(4 downto 0);
    else
      op  := cpi.ex.inst(31 downto 30);
      rd  := cpi.ex.inst(29 downto 25);
      op3 := cpi.ex.inst(24 downto 19);
      rs1 := cpi.ex.inst(18 downto 14);
      rs2 := cpi.ex.inst(4 downto 0);
    end if;

    if (op = LDST) and (op3(2) = '1') then rs1 := rd; end if;

    rfi1.rd1addr(3 downto 0) <= rs1(4 downto 1); rfi1.rd2addr(3 downto 0) <= rs2(4 downto 1);
    rfi2.rd1addr(3 downto 0) <= rs1(4 downto 1); rfi2.rd2addr(3 downto 0) <= rs2(4 downto 1);
    rfi1.ren1 <= '1'; rfi1.ren2 <= '1'; rfi2.ren1 <= '1'; rfi2.ren2 <= '1';
    cpo.ldlock <= ldlock;

    op1 := rfo1.data1(31 downto 0) & rfo2.data1(31 downto 0);
    op2 := rfo1.data2(31 downto 0) & rfo2.data2(31 downto 0);

    -- generate store data
    if  (cpi.ex.inst(20 downto 19) = "10") then  -- STDFQ
      if (cpi.ex.cnt /= "10") then stdata := eu.pc(31 downto 2) & "00";
      else stdata := eu.inst; end if;
    elsif  ((cpi.ex.inst(25) = '0') and (cpi.ex.cnt /= "10")) then  -- STF/STDF
      stdata := op1(63 downto 32);
    else stdata := op1(31 downto 0); end if;
    if (ex.cpins = store) and (ex.acsr = '1') then		-- STFSR
      stdata :=  rx.csr.rd & "00" & rx.csr.tem & "000" & 
      	std_logic_vector(FPUVER) & rx.csr.tt & qne & '0' & rx.csr.cc & 
	rx.csr.aexc & rx.csr.cexc;
    end if;
    cpo.data <= stdata;

    -- check if an execution unit is available
    if (ex.cpins = cpop) and (holdn = '1') and (cpi.ex.annul = '0') then
      ccv := ccv or ex.wrcc;
      if (eu.status = free) or ((eu.status = ready) and (wb = '1')) then
	rxv.start := '1'; 
        euiv.start := '1';
        if cpi.flush = '0' then euv.status := started; end if;
	euv.rd := cpi.ex.inst(29 downto 25);
        euv.rs1 := cpi.ex.inst(18 downto 14);
        euv.rs2 := cpi.ex.inst(4 downto 0);
	euv.wreg := ex.wreg;
	euv.rreg1 := ex.rreg1;
	euv.rreg2 := ex.rreg2;
	euv.rs1d := ex.rs1d;
	euv.rs2d := ex.rs2d;
	euv.rdd := ex.rdd;
	euv.wrcc := ex.wrcc;
      else rxv.holdn := '0'; rv.start := '1'; end if;
    end if;  
    if cpi.flush = '1' then
      rxv.start := '0'; euiv.start := '0';
    end if;

-------------------------------------------------------------
-- memory stage
-------------------------------------------------------------

    euiv.load := rx.start or rx.starty;
    if (rx.holdn = '0') and  (xholdn = '1') and (cpi.flush = '0') and
        (euo.busy = '0')
    then
      euiv.start := not rx.startx;
      euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
    end if;
    if (rx.holdn = '0') and ((eu.status <= free) or (wb = '1'))
    then
      euiv.load := rx.starty;
      euiv.start := not (rx.starty or rx.startx);
      euv.status := started;
      euv.rs1 := cpi.me.inst(18 downto 14);
      euv.rs2 := cpi.me.inst(4 downto 0);
      euv.rd := cpi.me.inst(29 downto 25);
      euv.wreg := me.wreg;
      euv.rreg1 := me.rreg1;
      euv.rreg2 := me.rreg2;
      euv.rs1d := me.rs1d;
      euv.rs2d := me.rs2d;
      euv.rdd := me.rdd;
      euv.wrcc := me.wrcc;
      euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
      rxv.holdn := '1';
    end if;
    euiv.start := euiv.start and not cpi.flush;
    rxv.starty := euiv.start;
    rxv.startx := (rx.startx or euiv.start) and (not holdn) and not cpi.flush;
    ccv := ccv or me.wrcc;
    if (cpi.flush = '1') or (rx.state /= nominal) then rxv.holdn := '1'; end if;
    if holdn = '0' then rxv.wbok := rx.wbok; end if;
    if (me.cpins = cpop) and (holdn = '1') then
      if ((cpi.flush and not eu.wbok) = '1') then euv.rst := '1';
      else rxv.wbok := not cpi.me.annul; end if;
    end if;

    -- regfile bypass
    if (rx.waddr = cpi.me.inst(18 downto 15)) then
      if (rx.wren(0) = '1') then op1(63 downto 32) := rx.res(63 downto 32); end if;
      if (rx.wren(1) = '1') then op1(31 downto 0) := rx.res(31 downto 0); end if;
    end if;
    if (rx.waddr = cpi.me.inst(4 downto 1)) then
      if (rx.wren(0) = '1') then op2(63 downto 32) := rx.res(63 downto 32); end if;
      if (rx.wren(1) = '1') then op2(31 downto 0) := rx.res(31 downto 0); end if;
    end if;

    -- optionally forward data from write stage
    if rfi1.wren = '1' then
      if cpi.me.inst(18 downto 15) = rfi1.wraddr(3 downto 0) then 
        op1(63 downto 32) := rfi1.wrdata(31 downto 0);
      end if;
      if cpi.me.inst(4 downto 1) = rfi1.wraddr(3 downto 0) then 
        op2(63 downto 32) := rfi1.wrdata(31 downto 0);
      end if;
    end if;
    if rfi2.wren = '1' then
      if cpi.me.inst(18 downto 15) = rfi2.wraddr(3 downto 0) then 
        op1(31 downto 0) := rfi2.wrdata(31 downto 0);
      end if;
      if cpi.me.inst(4 downto 1) = rfi2.wraddr(3 downto 0) then 
        op2(31 downto 0) := rfi2.wrdata(31 downto 0);
      end if;
    end if;


    -- align single operands
    if me.rs1d = '0' then
      if cpi.me.inst(14) = '0' then op1 := op1(63 downto 32) & op1(63 downto 32);
      else op1 := op1(31 downto 0) & op1(31 downto 0); end if;
    end if;
    if me.rs2d = '0' then
      if cpi.me.inst(0) = '0' then op2 := op2(63 downto 32) & op2(63 downto 32);
      else op2 := op2(31 downto 0) & op2(31 downto 0); end if;
    end if;

    -- drive EU operand inputs
    euiv.op1 := op1; euiv.op2 := op2;

    cpo.holdn <= rx.holdn;

-------------------------------------------------------------
-- write stage
-------------------------------------------------------------

    wrdata := cpi.lddata & cpi.lddata;
    if (cpi.wr.annul or cpi.flush) = '0' then
      case wr.cpins is
      when load =>
        if (wr.wreg = '1') then
          if cpi.wr.cnt = "00" then
            wren(0) := not cpi.wr.inst(25);
            wren(1) := cpi.wr.inst(25); 
	  else wren(1) := '1'; end if;
        end if;
	if (wr.acsr and holdn) = '1' then 
	  rxv.csr.cexc := cpi.lddata(4 downto 0);
	  rxv.csr.aexc := cpi.lddata(9 downto 5);
	  rxv.csr.cc  := cpi.lddata(11 downto 10);
	  rxv.csr.tem  := cpi.lddata(27 downto 23);
	  rxv.csr.rd   := cpi.lddata(31 downto 30);
        end if;
      when store =>
	if wr.acsr = '1' then rxv.csr.tt := (others => '0'); end if;
        if (cpi.wr.inst(20 downto 19) = "10") then  -- STDFQ
          if qne = '1'then
            euv.status := free; euv.rst := '1'; euv.wbok := '0';
	  else
	    rxv.state := nominal;
	  end if;
	end if;
      when cpop =>
	-- dont assign PC and inst until here in case previous cpop trapped
        if holdn = '1' then euv.wbok := rx.wbok; end if;
          euv.inst := cpi.wr.inst;
          euv.pc := cpi.wr.pc;
      when others => null;
      end case;
    end if;
    if (wr.cpins = cpop) and (holdn = '1') and (eu.wbok = '0') and
       ((cpi.flush or cpi.wr.annul) = '1') 
    then
      if rx.state = nominal then euv.status := free; end if;
      euv.rst := '1'; euv.wbok := '0';
    end if;

    waddr := cpi.wr.inst(29 downto 26);

-------------------------------------------------------------
-- retire stage
-------------------------------------------------------------

    rtaddr := eu.rd(4 downto 1);
    if eu.rdd = '1' then rtdata := euo.res;
    else 
      rtdata(63 downto 32) := euo.res(63) & 
	  euo.res(59 downto 29);
      rtdata(31 downto 0) := rtdata(63 downto 32);
    end if;

    wren := wren and (holdn & holdn);

    if ((euo.exc(4 downto 0) and rx.csr.tem) /= "00000") or
       (euo.exc(5) = '1')
    then 
      cpexc := '1';
    end if;
    if (wren = "00") and (eu.status = ready) and (rx.state = nominal) and
    ((eu.wbok = '1') or ((cpi.flush = '0') and (rx.wbok = '1')))
    then
      waddr := rtaddr; wrdata := rtdata;
      euv.wbok := '0';
      if (holdn = '0') then rxv.wbok := '0'; end if;
      if cpexc = '0' then
        if (eu.wreg) = '1' then
          if (eu.rdd) = '1' then wren := "11";
	  else
            wren(0) := not eu.rd(0);
            wren(1) := eu.rd(0);
	  end if;
        end if;
        if eu.wrcc = '1' then
	  rxv.csr.cc := euo.cc;
        end if;
        rxv.csr.aexc := rx.csr.aexc or euo.exc(4 downto 0);
        if euv.status = ready then
          euv.status := free; 
        end if;
        wbv := '1';
        rxv.csr.cexc := euo.exc(4 downto 0);
      else
	rxv.state := excpend;
        if (euo.exc(5) = '1') then rxv.csr.tt := "011";
        else rxv.csr.tt := "001"; end if;
      end if;
    end if;  

    if cpi.exack = '1' then rxv.state := exception; end if;
    if rxv.state = excpend then cpo.exc <= '1'; else cpo.exc <= '0'; end if;
    cpo.ccv   <= not ccv;
    cpo.cc    <= rx.csr.cc;

    rxv.res := wrdata;
    rxv.waddr := waddr;
    rxv.wren := wren;
    rfi1.wraddr(3 downto 0) <= waddr;
    rfi2.wraddr(3 downto 0) <= waddr;
    rfi1.wren <= wren(0);
    rfi2.wren <= wren(1);
    rfi1.wrdata(31 downto 0) <= wrdata(63 downto 32);
    rfi2.wrdata(31 downto 0) <= wrdata(31 downto 0);


-- reset
    if rst = '0' then
      rxv.holdn := '1'; rv.start := '0';
      rxv.state := nominal; rxv.csr.tt := (others => '0');
      rxv.startx := '0'; euv.status := free; euv.wbok := '0';
    end if;

    euin <= euv;
    eui <= euiv;
    exin <= ctrl;
    rin <= rv;
    rxin <= rxv;
    wb <= wbv;

  end process;

-- registers

  regs : process(clk)
  variable pc : std_logic_vector(31 downto 0);
  begin

    if rising_edge(clk) then

      if holdn = '1' then
        ex <= exin; me <= ex; wr <= me; r <= rin;
      end if;
      rx <= rxin; eu <= euin;
-- pragma translate_off
	if DEBUGFPU then
	  if (rfi1.wren = '1') then
	    print("0x" & tosth(cpi.wr.pc(31 downto 2) & "00") & ": %f" & 
		tostd(rfi1.wraddr(3 downto 0) & '0') &
		" = " & tosth(rfi1.wrdata(31 downto 0)));
	  end if;
	  if (rfi2.wren = '1') then
	    print("0x" & tosth(cpi.wr.pc(31 downto 2) & "00") & ": %f" & 
		tostd(rfi1.wraddr(3 downto 0) & '1') &
		" = " & tosth(rfi2.wrdata(31 downto 0)));
	  end if;
	end if;
-- pragma translate_on
    end if;
  end process;


-- regfile

  rf0: regfile_cp generic map (4, 32, 16)
       port map (rst, clk, rfi1, rfo1); 

  rf1: regfile_cp generic map (4, 32, 16)
       port map (rst, clk, rfi2, rfo2);

  fpu0 : fpu_core port map (
      clk   => clk,
      fpui.FpInst     => eui.opcode,
      fpui.FpOp       => eui.start,
      fpui.FpLd       => eui.load,
      fpui.Reset      => eui.flush,
      fpui.fprf_dout1 => eui.op1,
      fpui.fprf_dout2 => eui.op2,
      fpui.RoundingMode => rx.csr.rd,
      fpui.ss_scan_mode => gnd,
      fpui.fp_ctl_scan_in => gnd,
      fpui.fpuholdn => gnd,
      fpuo.FpBusy    => euo.busy,
      fpuo.FracResult => euo.res(51 downto 0),
      fpuo.ExpResult  => euo.res(62 downto 52),
      fpuo.SignResult => euo.res(63),
      fpuo.SNnotDB    => snnotdb,
      fpuo.Excep      => euo.exc,
      fpuo.ConditionCodes => euo.cc,
      fpuo.fp_ctl_scan_out => fp_ctl_scan_out);

end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -