📄 pci_mtf.vhd
字号:
-- Config space write access cwdata := pr.ad; if pr.cbe(3) = '1' then cwdata(31 downto 24) := cdata(31 downto 24); end if; if pr.cbe(2) = '1' then cwdata(23 downto 16) := cdata(23 downto 16); end if; if pr.cbe(1) = '1' then cwdata(15 downto 8) := cdata(15 downto 8); end if; if pr.cbe(0) = '1' then cwdata( 7 downto 0) := cdata( 7 downto 0); end if; if (r.t.csel and write_access) = '1' then case r.t.addr(7 downto 2) is when "000001" => -- 0x04, status & command v.comm.men := cwdata(1); if MASTER = 1 then v.comm.msen := cwdata(2); end if; v.comm.mwie := cwdata(4); v.comm.per := cwdata(6); v.stat.dped := r.stat.dped and not cwdata(24); -- Sticky bit v.stat.sta := r.stat.sta and not cwdata(27); -- Sticky bit v.stat.rta := r.stat.rta and not cwdata(28); -- Sticky bit v.stat.rma := r.stat.rma and not cwdata(29); -- Sticky bit v.stat.dpe := r.stat.dpe and not cwdata(31); -- Sticky bit when "000011" => -- 0x0c, latency & cacheline size if FIFO_DEPTH <= 7 then v.cline(FIFO_DEPTH - 1 downto 0) := cwdata(FIFO_DEPTH - 1 downto 0); else v.cline := cwdata(7 downto 0); end if; v.ltim := cwdata(15 downto 8); when "000100" => -- 0x10, BAR0 v.bar0 := cwdata(31 downto MADDR_WIDTH); if v.bar0 = zero(31 downto MADDR_WIDTH) then v.bar0_conf := '0'; else v.bar0_conf := '1'; end if; when "000101" => -- 0x14, BAR1 v.bar1 := cwdata(31 downto DMAMADDR_WIDTH); if v.bar1 = zero(31 downto DMAMADDR_WIDTH) then v.bar1_conf := '0'; else v.bar1_conf := '1'; end if; when "001111" => -- 0x3C, Interrupts & Latency timer settings v.intline := cwdata(7 downto 0); -- Interrupt line when others => end case; end if; -- Page bar write if (r.t.psel and write_access) = '1' then v.page := pr.ad(31 downto MADDR_WIDTH - 1); v.bt_enable := pr.ad(0); end if; -- Command and address decode case pr.cbe is when CONF_READ | CONF_WRITE => if pr.ad(1 downto 0) = "00" then chit := '1'; end if; if pr.host = '0' then --Active low if pr.ad(31 downto 11) = "000000000000000000000" then hosthit := '1'; end if; end if; when MEM_READ | MEM_WRITE => if pr.ad(31 downto MADDR_WIDTH) = r.bar0 then phit := r.bar0_conf and pr.ad(MADDR_WIDTH - 1); mhit0 := r.bar0_conf and not pr.ad(MADDR_WIDTH - 1); elsif pr.ad(31 downto DMAMADDR_WIDTH) = r.bar1 then mhit1 := r.bar1_conf; end if; when MEM_R_MULT | MEM_R_LINE | MEM_W_INV => if pr.ad(31 downto MADDR_WIDTH - 1) = r.bar0 & '0' then mhit0 := r.bar0_conf; elsif pr.ad(31 downto DMAMADDR_WIDTH) = r.bar1 then mhit1 := r.bar1_conf; end if; when others => phit := '0'; mhit0 := '0'; chit := '0'; mhit1 := '0'; end case; -- Hit detect hit := r.t.csel or r.t.msel or r.t.psel; if (hstart and r.pci.devsel) = '1' then if (r.t.pending or r.t.lwrite) = '0' then hstart := not hstart_ack; v.t.fifo.raddr := (others => '0'); end if; end if; -- Ready to transfer data if ((r.t.csel and not readt_dly) or r.t.psel) = '1' or ((((memwrite and not r.pci.devsel) = '1') or (memread = '1' and not (hstart_ack and v.t.wdel) = '1')) and ben_err = '0') then ready := '1'; else ready := '0'; t_read_side := r.t.read and not hstart; end if; -- Target timeout counter --if (hit and pr.trdy and not (pr.frame and pr.irdy)) = '1' then --if (hit and pr.trdy and not (pr.frame and pr.irdy) and v.t.wdel) = '1' then if (hit and pr.trdy and not (pr.frame and pr.irdy) and not ready) = '1' then if r.t.cnt /= "000" then v.t.cnt := r.t.cnt - 1; else tto := '1'; end if; else v.t.cnt := (0 => '0', others => '1'); end if;-- -- Ready to transfer data-- if ((r.t.csel and not readt_dly) or r.t.psel) = '1'-- or ((((memwrite and not r.pci.devsel) = '1')-- or (memread = '1' and not (hstart_ack and v.t.wdel) = '1')) and ben_err = '0')-- then ready := '1'; else ready := '0'; t_read_side := r.t.read and not hstart; end if; -- Terminate current transaction if (((r.t.fifo.waddr >= (FIFO_FULL - "10") and r.t.fifo.side = '1') or (t_valid = '0') or r.pci.stop = '0') and pcii.frame = '0') or ((r.t.read xor r.t.lwrite) = '0' and r.pci.devsel = '0') or (tto = '1') or (ben_err = '1') then term := '1'; else term := '0'; end if; -- Retry transfer if r.t.state = b_busy then if not ((r.t.read and not r.t.lwrite and hstart_ack and read_match) = '1' or (r.t.read or hstart or hstart_ack) = '0' or ((r.t.csel or r.t.psel) and not hstart and not hstart_ack) = '1') then retry := '1'; end if; end if; -- target state machine case r.t.state is when idle => if pr.frame = '0' then v.t.state := b_busy; end if; -- !HIT ? v.t.addr := pr.ad; if readpref = 1 then v.t.burst := '1'; else v.t.burst := pr.cbe(3); end if; v.t.read := not pr.cbe(0); v.t.mult := not pr.cbe(1); v.t.csel := (pr.idsel or hosthit) and chit; v.t.psel := phit; v.t.msel := r.comm.men and (mhit0 or mhit1); v.t.barsel := mhit1; when turn_ar => if pr.frame = '1' then v.t.state := idle; v.t.fifo.raddr := (others => '0'); -- fix reset fifo read address else v.t.state := b_busy; end if; -- !HIT ? v.t.addr := pr.ad; v.t.wdel := '1'; if readpref = 1 then v.t.burst := '1'; else v.t.burst := pr.cbe(3); end if; v.t.read := not pr.cbe(0); v.t.mult := not pr.cbe(1); v.t.csel := (pr.idsel or hosthit) and chit; v.t.psel := phit; v.t.msel := r.comm.men and (mhit0 or mhit1); v.t.barsel := mhit1; when b_busy => if (pr.frame and pr.irdy) = '1' then v.t.state := idle; elsif hit = '1' then v.t.state := s_data; v.t.fifo.raddr := r.t.fifo.raddr + (r.t.read and r.t.msel); readt_dly := '1'; if r.t.pending = '0' then v.t.pending := retry and not hstart_ack; end if; end if;-- else v.t.state := backoff; end if;-- We should not go to back off if the access wasn't to us when s_data => if r.t.pending = '1' then v.t.pending := not ((habort or not r.pci.trdy) and read_match); end if; if (pcii.frame = '0' and r.pci.stop ='0' and (r.pci.trdy or not pcii.irdy) = '1') then v.t.state := backoff; if r.t.last = '0' then v.t.last := r.t.msel and r.t.lwrite and v.t.wdel; end if; v.t.fifo.raddr := r.t.fifo.raddr - (r.t.read and r.t.msel and not fifort_limit);-- elsif (pcii.frame = '1' and (r.pci.trdy = '0' or r.pci.stop = '0')) then elsif (pcii.frame = '1' and (r.t.trdy_del = '0' or r.pci.stop = '0')) then -- (send last word in fifo) bug fix *** v.t.state := turn_ar; if r.t.last = '0' then v.t.last := r.t.msel and r.t.lwrite and v.t.wdel; end if; v.t.fifo.raddr := r.t.fifo.raddr - (r.t.read and r.t.msel and not fifort_limit); end if; when backoff => if pcii.frame = '1' then v.t.state := turn_ar; end if; end case; -- #TRDY assert if (v.t.state = s_data and habort = '0' and ready = '1' and retry = '0') then v.pci.trdy := '0'; end if; -- #STOP assert if (v.t.state = backoff or (v.t.state = s_data and ((tabort or ((term or retry) and not habort)) = '1'))) then v.pci.stop := '0'; end if; -- #DEVSEL assert if (((v.t.state = backoff and r.pci.devsel = '0') or v.t.state = s_data) and (read_match and tabort) = '0') then v.pci.devsel := '0'; end if; -- Enable #TRDY, #STOP and #DEVSEL if (v.t.state = s_data) or (v.t.state = backoff) or (v.t.state = turn_ar) then v.pci.oe_ctrl := not hit; else v.pci.oe_ctrl := '1'; end if; -- Signaled target abort if (r.pci.devsel and not (r.pci.stop or r.pci.oe_ctrl)) = '1' then v.stat.sta := '1'; end if; if r.t.state = s_data and v.t.state = s_data and r.pci.trdy = '0' and v.pci.trdy = '1' and v.t.wdel = '1' and pcii.frame = '0' then -- (send last word in fifo) bug fix *** v.t.trdy_del := '0'; else v.t.trdy_del := v.pci.trdy; end if; if r.t.state = s_data and r.pci.trdy = '1' and v.pci.trdy = '0' and pcii.frame = '0' then -- bug fix *** readt_dly := '1'; v.t.fifo.raddr := r.t.fifo.raddr + (r.t.read and not fifort_limit and t_valid); end if; -- Latched signals to AHB backend-- if (r.t.state = b_busy) then-- if (hstart or hstart_ack) = '0' then -- must be idle-- v.t.lwrite := not r.t.read;-- case pr.cbe is-- when "0000" => v.t.lsize := "10";-- when "1100" => v.t.lsize := "01";-- when "1110" => v.t.lsize := "00";-- when others => v.t.lsize := "10";-- end case;-- if r.t.msel = '1' then-- v.t.lburst := r.t.burst;-- if r.t.barsel = '0' then v.t.laddr := r.page & r.t.addr(MADDR_WIDTH-2 downto 0);-- else v.t.laddr := r2.dmapage & r.t.addr(DMAMADDR_WIDTH-1 downto 0); end if;-- v.t.lmult := r.t.mult;-- rtdone := '0'; v.t.fifo.waddr := (others => '0');-- hstart := r.t.read and r.t.msel;-- end if;-- end if;-- end if; -- Latched signals to AHB backend if (r.t.state = b_busy) then if (hstart or hstart_ack) = '0' then -- must be idle v.t.lwrite := not r.t.read; if endian = 0 then -- pci is little endian case pr.cbe is when "0000" => -- 32 bit access v.t.lsize := "10"; byteaddr := "00"; when "1100" => -- 16 bit v.t.lsize := "01"; byteaddr := "00"; when "0011" => v.t.lsize := "01"; byteaddr := "10"; when "1110" => -- 8 bit v.t.lsize := "00"; byteaddr := "00"; when "1101" => v.t.lsize := "00"; byteaddr := "01"; when "1011" => v.t.lsize := "00"; byteaddr := "10"; when "0111" => v.t.lsize := "00"; byteaddr := "11"; when others => v.t.lsize := "10"; end case; else -- big endian case pr.cbe is when "0000" => -- 32 bit access v.t.lsize := "10"; byteaddr := "00"; when "0011" => -- 16 bit v.t.lsize := "01"; byteaddr := "00"; when "1100" => v.t.lsize := "01"; byteaddr := "10"; when "0111" => -- 8 bit v.t.lsize := "00"; byteaddr := "00"; when "1011" => v.t.lsize := "00"; byteaddr := "01"; when "1101" => v.t.lsize := "00"; byteaddr := "10"; when "1110" => v.t.lsize := "00"; byteaddr := "11"; when others => v.t.lsize := "10"; end case; end if; if r.t.msel = '1' then v.t.lburst := r.t.burst; v.t.lcbe := pr.cbe; if r.t.barsel = '0' then v.t.laddr := r.page & r.t.addr(MADDR_WIDTH-2 downto 2) & byteaddr; else v.t.laddr := r2.dmapage & r.t.addr(DMAMADDR_WIDTH-1 downto 2) & byteaddr; end if; v.t.lmult := r.t.mult; rtdone := '0'; v.t.fifo.waddr := (others => '0'); hstart := r.t.read and r.t.msel; end if; end if; end if; -- Read data mux if r.t.csel = '1' then tad := cdata; elsif r.t.psel = '1' then tad(31 downto MADDR_WIDTH-1) := r.page; tad(MADDR_WIDTH-2 downto 0) := zero32(MADDR_WIDTH-2 downto 1) & r.bt_enable;-- elsif (r.t.state = b_busy or (r.pci.trdy or pcii.irdy) = '0') then tad := fifo1o.rdata(31 downto 0); elsif (r.t.state = b_busy or (r.pci.trdy or pcii.irdy) = '0' or r.t.wdel = '1') then tad := fifo1o.rdata(31 downto 0); -- bug fix *** end if; -- FIFO controller if ((fifowt_limit and write_access) = '1' or (r.t.last or rtdone) = '1') then if hstart = hstart_ack then if rtdone = '0' then hstart := not hstart_ack; v.t.fifo.side := hstart; end if; if r.t.last = '1' then rtdone := '1'; v.t.last := '0'; else v.t.fifo.waddr := (others => '0'); if rtdone = '1' then rtdone := '0'; hstart := '0'; v.t.fifo.side := '0'; end if; end if; end if; end if; if (fifort_limit and v.t.wdel) = '1' then if hstart_ack = '1' then hstart := '0'; v.t.fifo.raddr := (others => '0'); else v.t.fifo.raddr := (others => '0'); end if; end if;----- *** PCI TARGET END*** ------------- *** PCI MASTER *** -------- if MASTER = 1 then bus_idle := pcii.frame and pcii.irdy; data_transfer := not (pcii.trdy or r.pci.irdy); data_transfer_r := not (pr.trdy or pr.irdy); data_phase := not ((pcii.trdy and pcii.stop) or r.pci.irdy); targ_d_w_data := not (pr.stop or pr.trdy); targ_abort := pr.devsel and not pr.stop; -- Request from AHB backend to start PCI transaction if (pstart and not pstart_ack) = '1' then if (r.m.fstate = idle and r.m.request = '0') then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -