pci_mtf.vhd

来自「The GRLIB IP Library is an integrated se」· VHDL 代码 · 共 1,463 行 · 第 1/4 页

VHD
1,463
字号
          if r.t.lwrite = '1'  then            v.m.state := write; vdmai.busy := '1'; v.m.dmaddr := r.t.laddr;--            if rmvalid = '1' then v.m.state := write;--            else vdmai.start := '0'; v.m.state := stop; end if;          else v.m.state := read_w; end if;        else v.m.dmaddr := r.t.laddr; end if;      end if;    when write =>      vdmai.start := ((rmvalid and not fiform_limit) or (not dmao.active and not rmvalid));      if (dmao.active and dmao.ready) = '1' then        v.m.fifo.raddr := r2.m.fifo.raddr + (rmvalid and not fiform_limit and not dmao.mexc);        if (dmao.mexc = '1' or rmvalid = '0') then          habort := dmao.mexc and not r.t.lwrite; v.werr := r2.werr or (dmao.mexc and r.t.lwrite); v.m.state := stop; end if;      end if;    when read_w =>      vdmai.start := not (comp and dmao.active);      if dmao.mexc = '1' then habort := not r.t.lwrite; v.werr := '1'; v.m.state := stop;      elsif dmao.ready = '1' then        fifom_write := '1'; wmvalid := not (comp or dmao.mexc);        if comp = '1' then v.m.state := stop; v.m.fifo.waddr := r2.m.fifo.waddr + '1';        else v.m.fifo.waddr := r2.m.fifo.waddr + (not fifowm_limit); v.m.state := read; end if;      end if;    when read =>      vdmai.start := not (comp and dmao.active);      fifom_write := dmao.ready; wmvalid := not (comp or dmao.mexc);--      if ((comp and dmao.ready) or dmao.retry) = '1' then      if (comp and dmao.ready) = '1' then        v.m.state := stop; v.m.fifo.waddr := r2.m.fifo.waddr + '1';      elsif (dmao.active and dmao.ready) = '1' then        v.m.fifo.waddr := r2.m.fifo.waddr + (not dmao.mexc and not fifowm_limit);        if dmao.mexc = '1' then habort := not r.t.lwrite; v.werr := r2.werr or r.t.lwrite; v.m.state := stop; end if;      end if;    when stop =>      if hstart = '0' and ((r.t.lwrite and not fiform_limit) = '1' or wmdone = '1') then        v.m.state := idle; hstart_ack := '0';        v.m.fifo.side := '0'; habort := '0';        v.m.fifo.raddr := (others => '0');      else        comp := '1';        fiform_limit := r.t.lwrite;        fifowm_limit := not r.t.lwrite;      end if;    end case;    -- FIFO control    if fifowm_limit = '1' then--      if (((r2.m.fifo.side or hstart_ack or (not hstart)) = '0' and not (dmao.active and not dmao.ready) = '1')      if (((r2.m.fifo.side or hstart_ack or (not hstart)) = '0' and (dmao.ready or comp) = '1')      or ((hstart_ack and not hstart) = '1' and v.m.state = stop)) then        if v.m.state = stop then wmdone := '1';        else v.m.fifo.waddr := (others => '0'); end if;        hstart_ack := '1';        v.m.fifo.side := not r2.m.fifo.side;      end if;    elsif fiform_limit = '1' then      if dmao.active = '0' then        m_read_side := '1';        hstart_ack := '1';        v.m.fifo.raddr := (others => hstart);      end if;    end if;---- *** AHB MASTER END *** -------- *** AHB SLAVE *** ------    if MASTER = 1 then      -- Access decode      if (ahbsi.hready and ahbsi.hsel(hslvndx)) = '1' then        if (ahbsi.hmbsel(0) or ahbsi.hmbsel(1)) = '1' then          hsize := ahbsi.hsize(1 downto 0); v.s.htrans := ahbsi.htrans;          if (v.s.htrans(1) and r.comm.msen) = '1' then request := '1'; end if;        end if;      end if;      -- Access latches      if (request = '1' and r2.s.state = idle) then        if ahbsi.hmbsel(1)  = '1' then          if ahbsi.haddr(16) = '1' then -- Configuration cycles            v.s.maddr(31 downto 11) := (others =>'0');            v.s.maddr(conv_integer(ahbsi.haddr(15 downto 11)) + 10) := '1';            v.s.maddr(10 downto 0) := ahbsi.haddr(10 downto 0);            v.s.pcicomm := "101" & ahbsi.hwrite;          else -- I/O space access            v.s.maddr(31 downto 16) := r2.ioba;            v.s.maddr(15 downto 0) := ahbsi.haddr(15 downto 0);            v.s.pcicomm := "001" & ahbsi.hwrite;          end if;        else -- Memory space access          if conv_integer(ahbsi.hmaster) = dmamst then v.s.maddr := ahbsi.haddr;          else v.s.maddr := r2.pciba & ahbsi.haddr(27 downto 0); end if;          if ahbsi.hwrite = '1' then v.s.pcicomm := r2.wcomm & "111";          else v.s.pcicomm := ahbsi.hburst(0) & '1' & (r2.rcomm or not ahbsi.hburst(0)) & '0'; end if;        end if;        case hsize is        when "00" => v.s.be := "1110"; -- Decode byte enable        when "01" => v.s.be := "1100";        when "10" => v.s.be := "0000";        when others => v.s.be := "1111";        end case;      end if;      if ((rmdone and not r2.s.pcicomm(0)) = '1' and (r2.s.fifo.raddr + '1' + pcidc) = r.m.fifo.waddr) then rsvalid := '0'; end if;      -- FIFO address counters      if (r2.s.state = t_data or r2.s.state = w_wait) then        v.s.fifos_write := r2.s.pcicomm(0) and r2.s.htrans(1);        v.s.fifo.waddr := r2.s.fifo.waddr + r2.s.fifos_write;        v.s.fifo.raddr := r2.s.fifo.raddr + ((ahbsi.htrans(1) and not r2.s.pcicomm(0) and not fifors_limit and rsvalid) or not ahbsi.hready);      end if;      if pstart_ack = '1' then        if pabort = '1' then          if (r2.s.pcicomm = CONF_WRITE or r2.s.pcicomm = CONF_READ) then v.cfto := '1';          else v.s.perror := '1'; end if;        else v.s.perror := '0'; v.cfto := '0'; end if;      end if;    -- AHB slave state machine      case r2.s.state is      when idle =>        if request = '1' and p_done = '0' then          if ahbsi.hwrite = '1' then            v.s.state := w_wait;            v.s.fifo.side := '0';          else            pstart := '1'; v.s.state := r_wait;          end if;        end if;      when w_wait =>        if ((ahbsi.hready and not ahbsi.htrans(0)) = '1') then          v.s.state := w_done; fifows_limit := not wsvalid;        else          v.s.state := t_data;        end if;      when t_data =>        burst_read := ahbsi.htrans(1) and not fifors_limit;        if (fifows_stop and r2.s.fifos_write) = '1' then          if r2.s.fifo.side = '1' then v.s.state := w_done; end if;        elsif ((fifors_limit or not rsvalid) = '1' and v.s.htrans(1) = '1') then          if (r.m.fifo.side = '0') or (rsvalid = '0') then v.s.state := t_done;          else v.s.state := r_hold; end if;        end if;        if ((ahbsi.hready and not ahbsi.htrans(0)) = '1') then          if r2.s.pcicomm(0) = '1' then v.s.state := w_done; wsvalid := '0';          else v.s.state := t_done; end if;        end if;      when r_hold =>        s_read_side := '1';        if fifors_limit = '0' and ((pstart_ack or pstart) = '0') and request = '1'  then          v.s.state := t_data;        else v.s.hold := '1'; end if;      when r_wait =>        s_read_side := '0';        if (pstart_ack and request) = '1' then          v.s.state := t_data; hready := '0';        end if;      when w_done =>        v.s.state := t_done; wsvalid := '0';--        if (r2.s.htrans(1) or not fifows_limit) = '1' then--        if (r2.s.htrans(1) and fifows_limit) = '1' then          v.s.fifo.waddr := r2.s.fifo.waddr + r2.s.fifos_write;--          end if;        fifows_limit := '1';      when t_done =>        wsvalid := '0';        fifors_limit := not r2.s.pcicomm(0);        if (pstart or pstart_ack) = '0' then          v.s.state := idle; v.s.perror := '0';          v.s.fifo.waddr := (others => '0'); wsdone := '0'; fifows_limit := '0';          v.s.pcicomm := (0 => '1', others => '0'); -- default write        else fifows_limit := r2.s.pcicomm(0); end if;      end case;      -- Respond encoder        if v.s.state = t_data        or (v.s.state = w_wait and ahbsi.hwrite = '1') then          if r2.s.perror = '1' then hresp := HRESP_ERROR;          elsif wsvalid = '1' then hresp := HRESP_OKAY;          else hresp := HRESP_RETRY; end if;          v.s.perror := '0';        else hresp := HRESP_RETRY; end if;      if r.comm.msen = '0' then hresp := HRESP_ERROR; end if; -- Master disabled      if (v.s.htrans(1) and request) = '0' then hresp := HRESP_OKAY; end if; -- Response OK for BUSY and IDLE      if (hresp /= HRESP_OKAY or hready = '0') then v.s.hready := '0'; else v.s.hready := '1'; end if;      -- Dont change hresp during wait states      if ahbsi.hready = '0' then hresp := r2.s.hresp; end if;      v.s.hresp := hresp;      -- FIFO controller      if fifows_limit = '1' then        if (r2.s.fifos_write or not wsvalid) = '1' and (r2.s.fifo.side = '0' or pstart_ack = '1')   then          if wsvalid = '0' then wsdone := '1';          else v.s.fifo.waddr := (others => '0'); end if;          pstart := not pstart_ack;          v.s.fifo.side := pstart;        end if;      elsif ((r2.s.state = t_done or r2.s.state = r_hold) and fifors_limit = '1') then        if pstart_ack = '1' then pstart := '0'; v.s.fifo.raddr := (others => '0');        else v.s.fifo.raddr := (others => '0'); end if;      end if;--    end if;---- *** AHB SLAVE END *** -------- *** Sync Regs *** ----    v.trans(0) := pstart;    v.trans(1) := habort;    v.trans(2) := hstart_ack;    v.trans(3) := fifows_limit;    v.trans(4) := wsdone;    v.trans(5) := wmdone;    vdmai.address := r2.m.dmaddr;    -- input data for write accesses    if r2.s.pcicomm(0) = '1' then v.s.mdata := ahbsi.hwdata; end if;    -- output data for read accesses    if (ahbsi.htrans(1) and not r2.s.hold and not r2.s.pcicomm(0)) = '1' then v.s.mdata := fifo4o.rdata(31 downto 0); end if;    if rst = '0' then      v.s.state := idle;      v.m.state := idle;      v.s.perror := '0';      v.pciba := (others => '0');      v.trans := (others => '0');      v.m.fifo.waddr := (others => '0');      v.m.fifo.raddr := (others => '0');      v.s.fifo.waddr := (others => '0');      v.s.fifo.raddr := (others => '0');      v.m.fifo.side := '0';      v.s.fifo.side := '0';      v.wcomm := '0';      v.rcomm := '0';      v.werr := '0';      v.cfto := '0';      v.dmapage := (others => '0');      v.ioba := (others => '0');    end if;    r2in <= v; dmai <= vdmai;    apbo.prdata <= prdata;    ahbso.hready <= r2.s.hready;    ahbso.hresp  <= r2.s.hresp;    ahbso.hrdata <= r2.s.mdata;    ahbso.hindex <= hslvndx;    fifo1i.wen <= fifom_write;    fifo1i.waddr <= r2.m.fifo.side & r2.m.fifo.waddr;    fifo1i.wdata <= dmao.rdata;    fifo2i.ren <= '1';    fifo2i.raddr <= m_read_side & (r2.m.fifo.raddr + dmao.ready);    fifo3i.wen <= r2.s.fifos_write;    fifo3i.waddr <= r2.s.fifo.side & r2.s.fifo.waddr;    fifo3i.wdata <= r2.s.mdata;    fifo4i.ren <= '1';    fifo4i.raddr <= s_read_side & (r2.s.fifo.raddr + burst_read);  end process;  ahbso.hconfig <= hconfig when MASTER = 1 else (others => zero32);  ahbso.hcache <= '0';  apbo.pconfig <= pconfig;  apbo.pindex <= pindex;  ahbso.hsplit <= (others => '0');  ahbso.hirq   <= (others => '0');  apbo.pirq   <= (others => '0');-- PCI core (PCI clock domain)  pcicomb : process(pr, pcii, r, r2, fifo1o, fifo3o, roe_ad)  variable v : pci_reg_type;  variable chit, mhit0, mhit1, phit, hit, hosthit, ready, cwrite, retry : std_logic;  variable cdata, cwdata : std_logic_vector(31 downto 0);  variable comp : std_logic; -- Last transaction cycle on PCI bus  variable mto, tto, term, ben_err, lto : std_logic;  variable i : integer range 0 to NO_PCI_REGS;  variable tad, mad : std_logic_vector(31 downto 0);  variable pstart, habort, hstart_ack, wsdone, wmdone : std_logic;  variable hstart, pabort, pstart_ack, pcidc, rtdone, rmdone : std_logic;  variable fifort_limit, fifowt_limit, fiform_limit, fifowm_limit, fifowm_stop, t_valid : std_logic;  variable d_ready, tabort, backendnr : std_logic;  variable m_fifo_write, t_fifo_write, grant : std_logic;  variable write_access, memwrite, memread, read_match, m_read_side, t_read_side : std_logic;  variable readt_dly : std_logic; -- 1 turnaround cycle  variable bus_idle, data_transfer, data_transfer_r, data_phase, targ_d_w_data, targ_abort, m_request : std_logic;  variable voe_ad : std_logic_vector(31 downto 0);  variable oe_par   : std_logic;  variable oe_ad    : std_logic;  variable oe_ctrl  : std_logic;  variable oe_cbe   : std_logic;  variable oe_frame : std_logic;  variable oe_irdy  : std_logic;  variable oe_req   : std_logic;  variable oe_perr  : std_logic;  begin  -- Process defaults    v := r; v.pci.trdy := '1'; v.pci.stop := '1'; v.pci.frame := '1';    v.pci.oe_ad := '1'; v.pci.devsel := '1'; v.pci.oe_frame := '1';    v.pci.irdy := '1'; v.pci.req := '1'; hosthit := '0'; m_request := '0';    v.pci.oe_req := '0'; v.pci.oe_cbe := '1'; v.pci.oe_irdy := '1';    mto := '0'; tto := '0'; v.m.stop_req := '0'; lto := '0';    cdata := (others => '0'); retry := '0'; t_fifo_write := '0';    chit := '0'; phit := '0'; mhit0 := '0'; mhit1 := '0'; tabort := '0';    readt_dly := '0'; m_fifo_write := '0'; voe_ad := roe_ad;     tad := r.pci.ad; mad := r.pci.ad; grant := pcii.gnt; d_ready := '0';    m_read_side := not r2.s.fifo.side; t_read_side := not r2.m.fifo.side;    write_access := not r.t.read and not pr.irdy and not pr.trdy;    memwrite := r.t.msel and r.t.lwrite and not r.t.read;    memread := r.t.msel and not r.t.lwrite and r.t.read;    -- Synch registers    hstart := r.trans(0);    pabort := r.trans(1);    pstart_ack := r.trans(2);    pcidc := r.trans(3);    rtdone := r.trans(4);    rmdone := r.trans(5);    for i in 0 to NO_PCI_REGS - 1 loop      v.syncs(i)(csync) := r2.trans(i);     if csync /= 0 then v.syncs(i)(0) := r.syncs(i)(csync); end if;    end loop;    pstart     := r.syncs(0)(0);    habort     := r.syncs(1)(0);    hstart_ack := r.syncs(2)(0);    backendnr  := r.syncs(3)(0);    wsdone     := r.syncs(4)(0);    wmdone     := r.syncs(5)(0);    -- FIFO limit detector    if r.t.fifo.raddr = FIFO_FULL then fifort_limit := '1'; else fifort_limit := '0'; end if;    if r.t.fifo.waddr = FIFO_FULL then fifowt_limit := '1'; else fifowt_limit := '0'; end if;    if r.m.fifo.raddr = FIFO_FULL then fiform_limit := '1'; else fiform_limit := '0'; end if;    if r.m.fifo.waddr = FIFO_FULL then fifowm_limit := '1'; else fifowm_limit := '0'; end if;    if r.m.fifo.waddr(FIFO_DEPTH - 2 downto 1) = FIFO_FULL(FIFO_DEPTH - 2 downto 1) then fifowm_stop := '1'; else fifowm_stop := '0'; end if;    -- useful control variables    if (r.t.laddr = r.page & r.t.addr(MADDR_WIDTH-2 downto 0) or r.t.laddr = r2.dmapage & r.t.addr(DMAMADDR_WIDTH-1 downto 0))    and (r.t.lburst = r.t.burst) then read_match := r.t.pending; else read_match := r.t.csel or r.t.psel; end if;    if (pr.cbe = "0000" and r.t.lsize = "10") or (pr.cbe = "1100" and r.t.lsize = "01") or (pr.cbe = "1110" and r.t.lsize = "00")-- pragma translate_off    or (pr.cbe = "XXXX") -- For simulation purposes-- pragma translate_on    then ben_err := '0'; else ben_err := '1'; end if;    if r.stat.dpe = '0' then v.stat.dpe := not r.pci.perr; end if;----- *** PCI TARGET *** --------    -- Data valid?    if ((wmdone and not r.t.lwrite) = '1' and (r.t.fifo.raddr + '1') = r2.m.fifo.waddr) then t_valid := '0';    else t_valid := not fifowt_limit or not r.t.fifo.side; end if;    -- Step addresses    if (r.t.state = s_data or r.t.state = turn_ar or r.t.state = backoff) then      if (pcii.irdy or r.pci.trdy) = '0' then        v.t.addr := r.t.addr + ((r.t.csel and r.t.read) & "00");

⌨️ 快捷键说明

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