📄 dmactrl.vhd
字号:
v.htrans := "11"; else v.htrans := "01"; end if; if r.htrans(1) = '1' and ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY and pci_done = '1' then v.state := read5; v.htrans := "00"; elsif r.htrans(1) = '1' and ahbso1.hready = '0' and ahbso1.hresp = HRESP_RETRY then if dmao.active = '0' then v.two_in_buf := '1'; end if; -- two words in rbuf to store v.state := read4; v.htrans := "01"; end if; when read4 => -- PCI retry bufloc := 1; if dmao.ready = '1' then v.two_in_buf := '0'; end if; if dmao.start = '1' and r.two_in_buf = '0' then v.dmao_start := '1'; end if; if r.no_ws = '1' and r.dmao_start = '1' then vdmai.start := '0'; elsif dmao.start = '1' and r.two_in_buf = '0' then v.no_ws := '1'; vdmai.start := '0'; else vdmai.start := '1'; end if; if dmao.ready = '1' and r.no_ws = '1' and r.two_in_buf = '0' then v.first0 := '1'; v.first1 := '1'; v.no_ws := '0'; v.dmao_start := '0'; v.state := read1; end if; when read5 => -- PCI read done if dmao.start = '1' then v.first0 := '0'; -- first amba access elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit if dma_done = '0' or (r.first0 = '1' and dmao.start = '0') then vdmai.start := '1'; end if; if (dmao.ready and dmao.start) = '1' then bufloc := 1; v.no_ws := '1'; -- no wait state on AMBA ? else bufloc := 2; end if; if dmao.ready = '1' and dma_done = '1' then v.state := turn; end if; when write1 => -- Read first from AMBA bufloc := 0; v.first1 := '1'; v.no_ws := '0'; if dmao.start = '1' then v.first0 := '0'; -- first amba access elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit if dma_done = '1' and (r.first0 = '0' or dmao.start = '1') then vdmai.start := '0'; else vdmai.start := '1'; end if; if dmao.ready = '1' then if dma_done = '1' then v.state := write4; else v.state := write2; end if; v.htrans := "10"; -- start access to PCI end if; when write2 => -- Read from AMBA and write to PCI bufloc := 0; if (dmao.ready and dmao.start) = '1' then v.no_ws := '1'; end if; -- no wait state on AMBA ? if dmao.start = '1' then v.first0 := '0'; -- first amba access elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit if dmao.ready = '1' then -- Data ready write to PCI v.htrans := "11"; if dma_done = '1' then v.state := write4; end if; else v.htrans := "01"; end if; if ahbso1.hready = '0' then vdmai.start := '0'; if v.no_ws = '1' then bufloc := 1; end if; if dmao.active = '0' then v.state := writeb; -- AMBA 1k limit else v.state := write3; end if; elsif dma_done = '0' or (r.first0 = '1' and dmao.start = '0') then vdmai.start := '1'; end if; when writeb => -- AMBA 1k limit and PCI retry bufloc := 1; if dmao.active = '1' then vdmai.start := '0'; else vdmai.start := '1'; end if; if dmao.ready = '1' then v.state := write3; end if; when write3 => -- Retry from PCI bufloc := 1; --if ahbso1.hready = '1' then v.htrans := "10"; -- wait for AMBA access to be done before retry if (ahbso1.hready and (dmao.ready or not dmao.active)) = '1' then v.htrans := "10"; else v.htrans := "01"; end if; if r.htrans(1) = '1' and ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then if pci_done = '1' then v.htrans := "00"; v.state := turn; elsif dma_done = '1' and r.burstl_a(0) = '0' then v.htrans := "01"; v.state := write4; else v.htrans := "11"; v.first0 := '1'; v.state := write2; end if; end if; when write4 => -- Done read AMBA v.htrans := "11"; if pci_done = '1' and ahbso1.hready = '1' and r.htrans(1) = '1' then v.htrans := "00"; v.state := turn; elsif ahbso1.hready = '0' then v.state := write3; v.htrans := "01"; end if; when turn => v.htrans := "00"; -- can't switch of dma until AMBA slave is idle if (ahbsi0.hsel(slvindex) = '0' and r.ahb0_retry = '0' and ahbsi0.hready = '1') or (ahbsi0.htrans = "00" and ahbsi0.hready = '1') or r.ahb0_retry = '1' then v.ready := '1'; v.first1 := '1'; v.start_req := '0'; v.start := '0'; v.state := idle; end if; end case; if ((r.htrans(1) and ahbso1.hready) = '1' and ahbso1.hresp = HRESP_OKAY) then -- PCI access done v.burstl_p := r.burstl_p - '1'; -- dec counter v.addr1 := r.addr1 + '1'; -- inc address (PCI) if (r.write = '0' or r.state = write4 or r.state = write3) then if r.state /= read1 and r.state /= read2 and (v.no_ws = '1' or r.state = write3) and v.blimit = '0' then v.rbuf(0) := r.rbuf(1); -- dont update if wait states v.rbuf(1) := r.rbuf(2); -- end if; if r.write = '0' then v.rbuf(bufloc) := ahbso1.hrdata; end if; -- PCI to AMBA end if; -- if wait states store in buf(2) else end if; -- in buf(1). Frist word in buf(0) if dmao.ready = '1' then -- AMBA access done v.burstl_a := r.burstl_a - '1'; -- dec counter v.addr0 := r.addr0 + 1; -- inc address (AMBA master) if r.write = '1' then if r.state /= write3 and bufloc = 0 then -- dont update if retry from PCI v.rbuf(0) := r.rbuf(1); v.rbuf(1) := r.rbuf(2); end if; v.rbuf(bufloc) := dmao.rdata; -- AMBA to PCI elsif r.write = '0' and (r.first0 = '1' or v.state = read4 or r.state = read5 or (v.no_ws = '0' or r.blimit = '1')) then v.rbuf(0) := r.rbuf(1); -- update when data is written if wait states or PCI retry or PCI done v.rbuf(1) := r.rbuf(2); end if; end if; if (ahbso1.hresp = HRESP_ERROR or (dmao.mexc or dmao.retry) = '1') then v.err := '1'; v.state := turn; v.htrans := HTRANS_IDLE; end if; --cancel dma if r.start = '1' and r.start_req = '0' then v.state := turn; end if; if rst = '0' then v.state := idle; v.start := '0'; v.start_req := '0'; v.write := '0'; v.err := '0'; v.ready := '0'; v.first1 := '1'; v.two_in_buf := '0'; v.hmbsel := (others => '0'); v.addr1 := (others => '0'); end if; if r.start = '1' then -- new *** ??? ahbsi1.hsel <= (others => '1'); ahbsi1.hmbsel(0 to 3) <= r.hmbsel; ahbsi1.hsize <= "010"; ahbsi1.hwrite <= r.write; ahbsi1.htrans <= v.htrans;-- ahbsi1.haddr <= r.addr1 & "00"; ahbsi1.haddr <= v.addr1 & "00"; ahbsi1.hburst <= "001"; ahbsi1.hwdata <= r.rbuf(0); ahbsi1.hready <= ahbso1.hready; ahbsi1.hmaster <= conv_std_logic_vector(hindex,4); ahbso0 <= slvbusy; else ahbsi1.hsel <= ahbsi0.hsel; ahbsi1.hmbsel(0 to 3) <= ahbsi0.hmbsel(0 to 3); ahbsi1.hsize <= ahbsi0.hsize; ahbsi1.hwrite <= ahbsi0.hwrite; ahbsi1.htrans <= ahbsi0.htrans; ahbsi1.haddr <= ahbsi0.haddr; ahbsi1.hburst <= ahbsi0.hburst; ahbsi1.hwdata <= ahbsi0.hwdata; ahbsi1.hready <= ahbsi0.hready; ahbsi1.hmaster <= ahbsi0.hmaster; ahbso0 <= ahbso1; v.state := idle; end if; dmai <= vdmai; rin <= v; apbo.pconfig <= pconfig; apbo.prdata <= pdata; apbo.pirq <= (others => '0'); apbo.pindex <= pindex; ahbsi1.hirq <= (others => '0'); ahbsi1.hprot <= (others => '0'); ahbsi1.hmastlock <= '0'; ahbsi1.hcache <= '0'; end process; cpur : process (clk) begin if rising_edge (clk) then r <= rin; end if; end process; ahbmst0 : pciahbmst generic map (hindex => hindex, devid => GAISLER_DMACTRL, incaddr => 1) port map (rst, clk, dmai, dmao, ahbmi, ahbmo);-- pragma translate_off bootmsg : report_version generic map ("dmactrl" & tost(pindex) & ": 32-bit DMA controller & AHB/AHB bridge rev " & tost(REVISION));-- pragma translate_onend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -