📄 pci_mtf.vhd
字号:
p_done := pstart_ack or pabort; if r2.m.fifo.raddr = FIFO_FULL then fiform_limit := '1'; else fiform_limit := '0'; end if; if r2.m.fifo.waddr = FIFO_FULL then fifowm_limit := '1'; else fifowm_limit := '0'; end if; if r2.s.fifo.raddr = FIFO_FULL then fifors_limit := '1'; else fifors_limit := '0'; end if; if r2.s.fifo.waddr = FIFO_FULL then fifows_limit := '1'; else fifows_limit := '0'; end if; if r2.s.fifo.waddr(FIFO_DEPTH - 2 downto 1) = FIFO_FULL(FIFO_DEPTH - 2 downto 1) then fifows_stop := '1'; else fifows_stop := '0'; end if;---- *** APB Control & Status regs *** ---- if (apbi.psel(pindex) and apbi.penable) = '1' then case apbi.paddr(4 downto 2) is when "000" => if apbi.pwrite = '1' then v.pciba := apbi.pwdata(31 downto 28); v.werr := r2.werr and not apbi.pwdata(14); v.wcomm := apbi.pwdata(10) and r.comm.mwie; v.rcomm := apbi.pwdata(9); end if; prdata := r2.pciba & "00000" & r.ltim & r2.werr & not pr.host & r.comm.msen & r.comm.men & r2.wcomm & r2.rcomm & r2.cfto & r.cline; when "001" => prdata := r.bar0(31 downto MADDR_WIDTH) & addzero(MADDR_WIDTH-1 downto 0); when "010" => prdata := r.page(31 downto MADDR_WIDTH-1) & addzero(MADDR_WIDTH-2 downto 1) & r.bt_enable; when "011" => prdata := r.bar1(31 downto DMAMADDR_WIDTH) & addzero(DMAMADDR_WIDTH-1 downto 0); when "100" => if apbi.pwrite = '1' then v.dmapage(31 downto DMAMADDR_WIDTH) := apbi.pwdata(31 downto DMAMADDR_WIDTH); end if; prdata := r2.dmapage(31 downto DMAMADDR_WIDTH) & addzero(DMAMADDR_WIDTH-1 downto 0); when "101" => if apbi.pwrite = '1' then v.ioba := apbi.pwdata(31 downto 16); end if; prdata := r2.ioba & addzero(15 downto 4) & hstart & hstart_ack & pstart & pstart_ack; when "110" => prdata(1) := r.comm.men; prdata(2) := r.comm.msen; prdata(4) := r.comm.mwie; prdata(6) := r.comm.per; prdata(24) := r.stat.dped; prdata(26) := '1'; prdata(27) := r.stat.sta; prdata(28) := r.stat.rta; prdata(29) := r.stat.rma; prdata(31) := r.stat.dpe; when others => end case; end if;---- *** AHB MASTER *** ---- -- Burst control if (r2.m.state = read or r2.m.state = read_w) then if r.t.lmult = '1' then comp := fifowm_limit and r2.m.fifo.side; elsif r.t.lburst = '1' then if r2.clscnt(8) = '1' then comp := '1'; else v.clscnt := r2.clscnt - (dmao.active and dmao.ready); end if; else comp := '1'; end if; else v.clscnt := '0' & (r.cline - '1'); -- set burst counter to cache line size end if; if (rtdone = '1' and (r2.m.fifo.raddr + '1') = r.t.fifo.waddr) then rmvalid := '0'; end if; --step DMA address if dmao.ready = '1' then v.m.dmaddr(31 downto 2) := r2.m.dmaddr(31 downto 2) + '1'; end if; -- AHB master state machine case r2.m.state is when idle => v.m.read_half := '0'; if hstart = '1' then wmdone := '0'; fifowm_limit := '0'; vdmai.start := '1'; v.m.fifo.waddr := (others => '0'); -- if dmao.active = '1' then -- zero ws fix if r.t.lwrite = '1' then v.m.state := write; v.m.dmaddr := r.t.laddr; --vdmai.busy := '1'; -- 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 fiform_limit = '1' then if fiform_limit = '1' and dmao.start = '1' then -- 1k bug fix (store last word in first v.m.read_half := '1'; -- fifo half if addr = 0x400 ...) end if; -- don't start again until pci side is done filling fifo, bug fix kc if r2.m.read_half = '1' then if rtdone = '1' then vdmai.start := ((rmvalid and not fiform_limit) or (not dmao.active and not rmvalid)); end if; else --vdmai.start := ((rmvalid and not fiform_limit) or (not dmao.active and not rmvalid)); -- 1k bug fix (store last word in first fifo half if addr = 0x400 ...) vdmai.start := ((rmvalid and not v.m.read_half) or (not dmao.active and not rmvalid)); end if; 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 if dmao.active = '0' and dmai.start = '0' then -- 1k bug fix *** m_read_side := '1'; hstart_ack := '1';-- v.m.fifo.raddr := (others => hstart); v.m.fifo.raddr := (others => '0'); -- 1k bug fix *** 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; if (v.s.htrans(1) and r.comm.msen) = '1' then -- fix access control *** ahb_access := '1'; --if (r2.s.state /= r_wait and r2.s.state /= r_hold) or r2.s.hmaster = ahbsi.hmaster then --if (r2.s.state = idle or r2.s.state = t_done) or r2.s.hmaster = ahbsi.hmaster then if (r2.s.state = idle) or r2.s.hmaster = ahbsi.hmaster then request := '1'; end if; 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.maddr(10 downto 0) := ahbsi.haddr(10 downto 2) & "00"; 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; else v.s.maddr := r2.pciba & ahbsi.haddr(27 downto 2) & "00"; 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; if endian = 0 then -- pci is little endian case hsize is when "00" => -- Decode byte enable case ahbsi.haddr(1 downto 0) is when "00" => v.s.be := "1110"; when "01" => v.s.be := "1101"; when "10" => v.s.be := "1011"; when "11" => v.s.be := "0111"; when others => v.s.be := "1111"; end case; when "01" => case ahbsi.haddr(1 downto 0) is when "00" => v.s.be := "1100"; when "10" => v.s.be := "0011"; when others => v.s.be := "1111"; end case; when "10" => v.s.be := "0000"; when others => v.s.be := "1111"; end case; else -- pci is big endian case hsize is when "00" => -- Decode byte enable case ahbsi.haddr(1 downto 0) is when "00" => v.s.be := "0111"; when "01" => v.s.be := "1011"; when "10" => v.s.be := "1101"; when "11" => v.s.be := "1110"; when others => v.s.be := "1111"; end case; when "01" => case ahbsi.haddr(1 downto 0) is when "00" => v.s.be := "0011"; when "10" => v.s.be := "1100"; when others => v.s.be := "1111"; end case; when "10" => v.s.be := "0000"; when others => v.s.be := "1111"; end case; end if; 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 if (r2.s.state = t_data or r2.s.state = w_wait or -- bug fix *** (r2.s.state = r_hold and fifors_limit = '0' and ((pstart_ack or pstart) = '0') and request = '1')) then -- (r_hold -> t_data) bug fix *** 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; v.s.hmaster := ahbsi.hmaster; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -