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 + -
显示快捷键?