📄 dmactrl.vhd
字号:
-------------------------------------------------------------------------------- This file is a part of the GRLIB VHDL IP LIBRARY-- Copyright (C) 2003, Gaisler Research---- This program is free software; you can redistribute it and/or modify-- it under the terms of the GNU General Public License as published by-- the Free Software Foundation; either version 2 of the License, or-- (at your option) any later version.---- This program is distributed in the hope that it will be useful,-- but WITHOUT ANY WARRANTY; without even the implied warranty of-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-- GNU General Public License for more details.---- You should have received a copy of the GNU General Public License-- along with this program; if not, write to the Free Software-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- Entity: dmactrl-- File: dmactrl.vhd-- Author: Alf Vaerneus - Gaisler Research-- Modified: Nils-Johan Wessman - Gaisler Research-- Description: Simple DMA controller------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;library grlib;use grlib.amba.all;use grlib.stdlib.all;use grlib.devices.all;library gaisler;use gaisler.misc.all;use gaisler.pci.all;entity dmactrl is generic ( hindex : integer := 0; slvindex : integer := 0; pindex : integer := 0; paddr : integer := 0; pmask : integer := 16#fff#; blength : integer := 4 ); port ( rst : in std_logic; clk : in std_logic; apbi : in apb_slv_in_type; apbo : out apb_slv_out_type; ahbmi : in ahb_mst_in_type; ahbmo : out ahb_mst_out_type; ahbsi0 : in ahb_slv_in_type; ahbso0 : out ahb_slv_out_type; ahbsi1 : out ahb_slv_in_type; ahbso1 : in ahb_slv_out_type );end;architecture rtl of dmactrl isconstant BURST_LENGTH : integer := blength;constant REVISION : integer := 0;constant pconfig : apb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_DMACTRL, 0, REVISION, 0), 1 => apb_iobar(paddr, pmask));type state_type is(idle, read1, read2, read3, read4, read5, write1, write2, writeb, write3, write4, turn); type rbuf_type is array (0 to 2) of std_logic_vector(31 downto 0);type dmactrl_reg_type is record state : state_type; addr0 : std_logic_vector(31 downto 2); addr1 : std_logic_vector(31 downto 2); hmbsel : std_logic_vector(0 to NAHBAMR-1); htrans : std_logic_vector(1 downto 0); rbuf : rbuf_type; write : std_logic; start_req : std_logic; start : std_logic; ready : std_logic; err : std_logic; first0 : std_logic; first1 : std_logic; no_ws : std_logic; -- no wait states blimit : std_logic; -- 1k limit dmao_start: std_logic; two_in_buf: std_logic; -- two words in rbuf to be stored burstl_p : std_logic_vector(BURST_LENGTH - 1 downto 0); -- pci access counter burstl_a : std_logic_vector(BURST_LENGTH - 1 downto 0); -- amba access counter ahb0_htrans : std_logic_vector(1 downto 0); ahb0_hready : std_logic; ahb0_retry : std_logic; ahb0_hsel : std_logic; start_del : std_logic;end record;signal r,rin : dmactrl_reg_type;signal dmai : ahb_dma_in_type;signal dmao : ahb_dma_out_type;begin comb : process(rst,r,dmao,apbi,ahbsi0,ahbso1) variable v : dmactrl_reg_type; variable vdmai : ahb_dma_in_type; variable pdata : std_logic_vector(31 downto 0); variable slvbusy : ahb_slv_out_type; variable dma_done, pci_done : std_logic; variable bufloc : integer range 0 to 2; begin slvbusy := ahbso1; v := r; vdmai.burst := '1'; vdmai.address := r.addr0 & "00"; vdmai.write := not r.write; vdmai.start := '0'; vdmai.size := "10"; vdmai.wdata := r.rbuf(0); pdata := (others => '0'); vdmai.busy := '0'; vdmai.irq := '0'; bufloc := 0; v.start_del := r.start; slvbusy.hready := '1'; slvbusy.hindex := hindex; --slvbusy.hresp := "00"; v.ahb0_htrans := ahbsi0.htrans; v.ahb0_retry := '0'; v.ahb0_hsel := ahbsi0.hsel(slvindex); v.ahb0_hready := ahbsi0.hready; -- AMBA busy response when dma is running if r.ahb0_retry = '1' then slvbusy.hresp := "10"; else slvbusy.hresp := "00"; end if; if r.ahb0_htrans = "10" and (r.start = '1') and r.ahb0_hsel = '1' and r.ahb0_hready = '1' then slvbusy.hready := '0'; slvbusy.hresp := "10"; v.ahb0_retry := '1'; end if; -- Done signals if (r.burstl_a(BURST_LENGTH - 1 downto 1) = zero32(BURST_LENGTH - 1 downto 1)) then -- AMBA access done dma_done := '1'; else dma_done := '0'; end if; if (r.burstl_p(BURST_LENGTH - 1 downto 1) = zero32(BURST_LENGTH - 1 downto 1)) then -- PCI access done pci_done := '1'; else pci_done := '0'; end if; -- APB interface if (apbi.psel(pindex) and apbi.penable) = '1' then case apbi.paddr(4 downto 2) is when "000" => if apbi.pwrite = '1' then v.start_req := apbi.pwdata(0); v.write := apbi.pwdata(1); v.ready := r.ready and not apbi.pwdata(2); v.err := r.err and not apbi.pwdata(3); v.hmbsel := apbi.pwdata(7 downto 4); end if; pdata := zero32(31 downto 8) & r.hmbsel & r.err & r.ready & r.write & r.start_req; when "001" => if apbi.pwrite = '1' then v.addr0 := apbi.pwdata(31 downto 2); end if; pdata := r.addr0 & "00"; when "010" => if apbi.pwrite = '1' then v.addr1 := apbi.pwdata(31 downto 2); end if; pdata := r.addr1 & "00"; when "011" => if apbi.pwrite = '1' then v.burstl_p := apbi.pwdata(BURST_LENGTH - 1 downto 0); v.burstl_a := apbi.pwdata(BURST_LENGTH - 1 downto 0); end if; pdata := zero32(31 downto BURST_LENGTH) & r.burstl_p; when others => end case; end if; -- can't start dma until AMBA slave is idle if r.start_req = '1' and (ahbsi0.hready = '1' and (ahbsi0.htrans = "00" or ahbsi0.hsel(slvindex) = '0')) then v.start := '1'; end if; case r.state is when idle => v.htrans := "00"; v.first0 := '1'; v.first1 := '1'; v.no_ws := '0'; v.dmao_start := '0'; v.blimit := '0'; if r.start = '1' then if r.write = '0' then v.state := read1; else v.state := write1; end if; end if; when read1 => -- Start PCI read bufloc := 0; v.htrans := "10"; if ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then if r.htrans(1) = '1' then if pci_done = '1' then v.htrans := "00"; v.state := read5; else v.htrans := "11"; v.state := read2; end if; end if; elsif ahbso1.hready = '0' then v.htrans := "11"; else v.htrans := "00"; end if; when read2 => -- fill rbuf (3 words) if r.first1 = '1' then bufloc := 1; -- store 3 words else bufloc := 2; end if; if ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then if r.htrans = "11" then v.first1 := '0'; if pci_done = '1' then v.htrans := "00"; v.state := read5; elsif r.first1 = '0' then v.htrans := "01"; v.state := read3; v.first0 := '1'; end if; end if; end if; when read3 => -- write to AMBA and read from PCI vdmai.start := '1'; bufloc := 1; if (dmao.ready and dmao.start) = '1' then bufloc := 1; v.no_ws := '1'; -- no wait state on AMBA ? else bufloc := 2; if dmao.active = '1' then v.no_ws := '0'; end if; end if; if dmao.active = '0' then v.blimit := '1'; else v.blimit := '0'; end if; if dmao.ready = '1' then v.first0 := '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -