📄 pci_mtf.vhd
字号:
if ((ahbsi.hready and not ahbsi.htrans(0)) = '1') then if r2.s.pcicomm(0) = '1' then --v.s.state := w_done; wsvalid := '0'; v.s.state := w_done; if ahbsi.htrans /= "00" then wsvalid := '0'; end if; -- fix dont set wsvalid if amba idle else -- (if wsvalid = 0 side is changed before last write v.s.state := t_done; -- to fifo if hrans = 00) wsvalid := '0'; -- Bug fix, must give RETRY here! /KC 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 if rmdone = '0' then -- bug fix *** v.s.state := t_data; burst_read := ahbsi.htrans(1) and not fifors_limit; -- bug fix *** else v.s.state := t_done; end if; elsif (ahbsi.hready = '1' and ahbsi.htrans = "00" and r2.s.hresp = HRESP_OKAY) then -- (idle -> t_done) bug fix *** v.s.state := t_done; 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; if r2.s.hmaster /= ahbsi.hmaster and conv_integer(ahbsi.hmaster) = dmamst and pstart_ack = '1' then -- if pcidma cancel read v.s.state := t_done; 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 = r_hold and v.s.hold = '0') -- bug fix *** or (v.s.state = t_done and r2.s.state = t_data) -- (end of trans) bug fix *** 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 (v.s.htrans(1) and ahb_access) = '0' then hresp := HRESP_OKAY; end if; -- Response OK for BUSY and IDLE -- *** access control fix 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'; if wsvalid = '0' or v.s.state = w_done then wsdone := '1'; -- fix set wsdone and pstart at the same time 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; -- Set last fifo side written so that PCI master knows when to stop if (r2.s.fifos_write = '1') then v.s.last_side := r2.s.fifo.side; 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 (ahbsi.htrans(1) and not r2.s.pcicomm(0)) = '1' then v.s.mdata := fifo4o.rdata(31 downto 0); end if; -- bug fix *** -- irq apbo.pirq <= (others => '0'); if irq /= 0 then if to_x01(pcii.host) = '0' then-- v.pciirq := r2.pciirq(0) & orv((not pcii.int) and conv_std_logic_vector(irqmask,4));-- apbo.pirq(irq) <= not r2.pciirq(1) and r2.pciirq(0); -- only generate irq on falling edges of pcii.int apbo.pirq(irq) <= orv((not pcii.int) and conv_std_logic_vector(irqmask,4)); end if; 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'); v.pciirq := "11"; end if; r2in <= v; dmai <= vdmai; apbo.prdata <= prdata; ahbso.hready <= r2.s.hready; ahbso.hresp <= r2.s.hresp; ahbso.hrdata <= byte_twist(r2.s.mdata, r.bt_enable); ahbso.hindex <= hslvndx; fifo1i.wen <= fifom_write; fifo1i.waddr <= r2.m.fifo.side & r2.m.fifo.waddr; fifo1i.wdata <= byte_twist(dmao.rdata, r.bt_enable); 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 <= byte_twist(r2.s.mdata, r.bt_enable); 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');-- 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 byteaddr : std_logic_vector(1 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; v.m.rmdone := '0'; byteaddr := "00"; 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)) if (r.t.laddr(31 downto 2) = r.page & r.t.addr(MADDR_WIDTH-2 downto 2) -- bug fix match if byte access or r.t.laddr(31 downto 2) = r2.dmapage & r.t.addr(DMAMADDR_WIDTH-1 downto 2)) and (r.t.lcbe = pr.cbe) -- bug fix match byte access 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; ben_err := '0'; 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"); readt_dly := '1'; if r.t.msel = '1' then v.t.wdel := (fifort_limit and r2.m.fifo.side) or r.t.lwrite; v.t.fifo.raddr := r.t.fifo.raddr + (r.t.read and not fifort_limit and t_valid); end if; end if; if write_access = '1' then v.t.fifo.waddr := r.t.fifo.waddr + (r.t.msel and not r.t.read and not ben_err); t_fifo_write := r.t.msel; v.t.addr := r.t.addr + ((r.t.csel and not r.t.read) & "00"); end if; tabort := habort; else v.t.wdel := '0'; end if; -- Config space read access case r.t.addr(7 downto 2) is when "000000" => -- 0x00, device & vendor id cdata := conv_std_logic_vector(DEVICE_ID, 16) & conv_std_logic_vector(VENDOR_ID, 16); when "000001" => -- 0x04, status & command cdata(1) := r.comm.men; cdata(2) := r.comm.msen; cdata(4) := r.comm.mwie; cdata(6) := r.comm.per; cdata(24) := r.stat.dped; cdata(26) := '1'; cdata(27) := r.stat.sta; cdata(28) := r.stat.rta; cdata(29) := r.stat.rma; cdata(31) := r.stat.dpe; when "000010" => -- 0x08, class code & revision cdata(31 downto 8) := conv_std_logic_vector(16#0B4000#,24); when "000011" => -- 0x0C, latency & cacheline size cdata(7 downto 0) := r.cline; cdata(15 downto 8) := r.ltim; when "000100" => -- 0x10, BAR0 cdata(31 downto MADDR_WIDTH) := r.bar0; when "000101" => -- 0x14, BAR1 cdata(31 downto DMAMADDR_WIDTH) := r.bar1; when "001111" => -- 0x3C, Interrupts & Latency timer settings cdata(7 downto 0) := r.intline; -- Interrupt line cdata(8) := '1'; -- Use interrupt pin INTA# if fifodepth < 11 then cdata(fifodepth+13) := '1'; end if; --Define wanted burst period when others => end case;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -