www.pudn.com > noc.rar > dma_ctrl.vhd


------------------------------------------------------------------ 
--								-- 
--	DMA_ctrl.vhd - DMA Control				-- 
--	Paul Dunn - Nallatech Ltd Copyright 1999		-- 
--	Description - 						-- 
--	This process feeds the user with the required DMA 	-- 
--	controls. 						-- 
--	This DMA control, contains two FIFOs one for outputting	-- 
--	data and the other for inputing data.			-- 
--	The empty and half-full flags are used as indicators	-- 
--	to other parts of the design as to whether they have	-- 
--	data or can receive data.				-- 
--	There are two DMA counts.  One counts data coming in 	-- 
--	and out of the user application.			-- 
--	The other counts data coming in and out from the 	-- 
--	Spartan interface.					-- 
--	DMA enable and DMA direction are generated elsewhere.	-- 
--								-- 
------------------------------------------------------------------ 
 
library IEEE; 
use IEEE.std_logic_1164.all; 
use IEEE.std_logic_unsigned.all; 
 
entity DMA_CTRL is 
    port (	-- Interface clock. 
        	CLK: in STD_LOGIC; 
       	 	-- Global reset. 
       	 	RST: in STD_LOGIC; 
        	-- DMA enabled. 
        	DMA_ENABLE: in STD_LOGIC; 
        	-- DMA direction. 
        	DMA_DIRECTION: in STD_LOGIC; 
        	-- Read DMA data. 
        	RD_DMA: in STD_LOGIC; 
        	-- Write DMA data. 
        	WR_DMA: in STD_LOGIC; 
        	-- Write DMA count. 
        	WR_COUNT: in STD_LOGIC; 
       	 	-- DMA input data. 
       	 	DMA_IN: in STD_LOGIC_VECTOR (31 downto 0); 
        	-- DMA count input data. 
        	COUNT_IN: in STD_LOGIC_VECTOR (31 downto 0); 
        	-- DMA write enable. 
        	DMA_WEN: in STD_LOGIC; 
        	-- DMA read enable. 
        	DMA_REN: in STD_LOGIC;	 
        	-- DMA reset. 
        	DMA_RST: in STD_LOGIC; 
        	-- Terminal count of DMA counter. 
        	TERM_CNT: out STD_LOGIC;	    
        	-- Local DMA buffer full. 
        	DMA_IN_FULL: out STD_LOGIC; 
        	-- Local DMA buffer empty. 
        	DMA_IN_EMPTY: out STD_LOGIC; 
        	-- Local DMA buffer full 
        	DMA_OUT_FULL: out STD_LOGIC; 
        	-- Local DMA buffer empty. 
        	DMA_OUT_EMPTY: out STD_LOGIC; 
        	-- DMA output data. 
        	DMA_OUT: out STD_LOGIC_VECTOR (31 downto 0); 
        	-- DMA count output data. 
        	COUNT_OUT: out STD_LOGIC_VECTOR (31 downto 0); 
        	-- DMA local buffer is ready for data. 
        	DMA_RDY: out STD_LOGIC; 
        	-- DMA local buffer has data ready to send. 
        	DMA_DATA_AVAILABLE: out STD_LOGIC; 
        	-- Current DMA count (from the perspective of the user application). 
        	DMA_COUNT: out STD_LOGIC_VECTOR (31 downto 0); 
        	-- DMA data. 
        	DMA_DATA: inout STD_LOGIC_VECTOR (31 downto 0) 
    		); 
end DMA_CTRL; 
 
architecture DMA_CTRL_arch of DMA_CTRL is 
 
-- Synchronous FIFO using LUT RAMs. 
component FWFRFF_32 generic (	NEEDBACKUPg : integer range 0 to 1 := 0; 
				ATLEASTNEMPTYg : integer range 0 to 15 := 8; 
				ATLEASTNFULLg : integer range 0 to 15 := 8 
				); 
			port (	DI : in std_logic_vector(31 downto 0); 
				DO : out std_logic_vector(31 downto 0); 
				WEN : in std_logic; 
				CLK : in std_logic; 
				REN : in std_logic; 
				GSR_RST : in std_logic; 
				SW_RST : in std_logic; 
				BACKUP : in std_logic; 
				FULL : out std_logic; 
				EMPTY : out std_logic; 
				N_EMPTY : out std_logic; 
				N_FULL : out std_logic 
				); 
end component; 
 
--component FIFO_32 
--	port (	RCLK : in std_logic; 
--		WCLK : in std_logic; 
--		READ_EN : in std_logic; 
--		WRITE_EN : in std_logic; 
--		FIFO_RST : in std_logic; 
--		D : in std_logic_vector (31 downto 0); 
--		Q : out std_logic_vector (31 downto 0); 
--		FIFO_STATUS : out std_logic_vector (4 downto 0); 
--		FIFO_FULL : out std_logic; 
--		FIFO_EMPTY : out std_logic 
--		); 
--end component; 
 
-- FIFO in/out buses. 
signal INFIFO_OUT : std_logic_vector (31 downto 0); 
signal OUTFIFO_IN : std_logic_vector (31 downto 0); 
 
-- DMA ready and data available signals. 
signal DMA_DATA_AVAILABLEl : std_logic; 
signal DMA_RDYl : std_logic; 
 
-- DMA counts. 
signal COUNT1, COUNT2 : std_logic_vector (31 downto 0); 
 
signal DMA_RSTi: std_logic; 
 
signal INFIFO_STATUS, OUTFIFO_STATUS: std_logic_vector(4 downto 0); 
signal INFIFO_FULL, OUTFIFO_FULL: std_logic; 
 
signal ZERO : std_logic; 
signal ZEROS : std_logic_vector (31 downto 0); 
signal ONE : std_logic_vector (31 downto 0); 
 
signal FIFO_RST: std_logic; 
 
begin 
 
ZERO <= '0'; 
ZEROS <= (others => '0'); 
ONE <= (0 => '1', others => '0');		 
 
-- Determine if DMA data bus is being driven. 
DMA_DATA <= INFIFO_OUT when DMA_DIRECTION='0' else (others => 'Z');  
OUTFIFO_IN <= DMA_DATA; 
 
-- Input FIFO.  Data from the Spartan. 
H1_INFIFO : FWFRFF_32 generic map (NEEDBACKUPg => 0, 
				ATLEASTNEMPTYg => 8, 
				ATLEASTNFULLg => 8 
				) 
		port map (	DI => DMA_IN, 
				DO => INFIFO_OUT, 
				WEN => WR_DMA, 
				CLK => CLK, 
				REN => DMA_REN, 
				GSR_RST => RST, 
				SW_RST => DMA_RST, 
				BACKUP => ZERO, 
				FULL => open, 
				EMPTY => DMA_DATA_AVAILABLEl, 
				N_EMPTY => open, 
				N_FULL => DMA_IN_FULL 
				);	 
 
DMA_IN_EMPTY <= DMA_DATA_AVAILABLEl;				 
 
--H1_INFIFO : FIFO_32 
--	port map (	 
--		RCLK => CLK, 
--		WCLK => CLK, 
--		READ_EN => DMA_REN, 
--		WRITE_EN => WR_DMA, 
--		FIFO_RST => FIFO_RST, 
--		D => DMA_IN, 
--		Q => INFIFO_OUT, 
--		FIFO_STATUS => INFIFO_STATUS, 
--		FIFO_FULL => INFIFO_FULL, 
--		FIFO_EMPTY => DMA_DATA_AVAILABLEl 
--		); 
 
--process (RST, CLK) 
--begin  
--	if RST='1' then 
--		DMA_IN_FULL <= '0'; 
--	elsif CLK'event and CLK='1' then 
--		DMA_IN_FULL <= '0'; 
--		if INFIFO_STATUS(2)='1' or INFIFO_STATUS(3)='1' or INFIFO_STATUS(4)='1' or INFIFO_FULL='1' then 
--			DMA_IN_FULL <= '1'; 
--		end if; 
--	end if; 
--end process; 
 
DMA_DATA_AVAILABLE <= not DMA_DATA_AVAILABLEl when DMA_DIRECTION='0' else '0'; 
 
-- Output FIFO.  Data to the Spartan. 
H2_OUTFIFO : FWFRFF_32 generic map(NEEDBACKUPg => 0, 
				ATLEASTNEMPTYg => 8, 
				ATLEASTNFULLg => 8 
				) 
		port map (	DI => OUTFIFO_IN, 
				DO => DMA_OUT, 
				WEN => DMA_WEN, 
				CLK => CLK, 
				REN => RD_DMA, 
				GSR_RST => RST, 
				SW_RST => DMA_RST, 
				BACKUP => ZERO, 
				FULL => open, 
				EMPTY => DMA_OUT_EMPTY, 
				N_EMPTY => open, 
				N_FULL => DMA_RDYl 
				);	 
 
DMA_OUT_FULL <= DMA_RDYl; 
 
--H2_OUTFIFO : FIFO_32 
--	port map (	 
--		RCLK => CLK, 
--		WCLK => CLK, 
--		READ_EN => RD_DMA, 
--		WRITE_EN => DMA_WEN, 
--		FIFO_RST => FIFO_RST, 
--		D => OUTFIFO_IN, 
--		Q => DMA_OUT, 
--		FIFO_STATUS => OUTFIFO_STATUS, 
--		FIFO_FULL => OUTFIFO_FULL, 
--		FIFO_EMPTY => DMA_OUT_EMPTY 
--		); 
 
--process (RST, CLK) 
--begin  
--	if RST='1' then 
--		DMA_RDYl <= '0'; 
--	elsif CLK'event and CLK='1' then 
--		DMA_RDYl <= '0'; 
--		if OUTFIFO_STATUS(2)='1' or OUTFIFO_STATUS(3)='1' or OUTFIFO_STATUS(4)='1' or OUTFIFO_FULL='1' then 
--			DMA_RDYl <= '1'; 
--		end if; 
--	end if; 
--end process; 
 
DMA_RDY <= not DMA_RDYl when DMA_DIRECTION='1' else '0'; 
 
-- DMA counters. 
-- One counter is for the user application and allows that application to know if it still has to read or write. 
-- One counter generates the terminal count for the main interface control.  This is decremented when data is written/read from the interface control. 
-- The counter value read back to the Spartan can either be one counter or the other depending on data direction.   
-- The Spartan is only concerned with data written into these local FIFOs. 
process (RST, CLK) 
begin 
	if RST='1' then 
		COUNT1 <= (others => '1'); 
		COUNT2 <= (others => '1'); 
	elsif CLK'event and CLK='1' then 
		if WR_COUNT='1' then 
			COUNT1 <= COUNT_IN; 
			COUNT2 <= COUNT_IN; 
		else 
			if DMA_DIRECTION='0' and DMA_REN='1' then 
				COUNT2 <= COUNT2-1; 
			elsif DMA_DIRECTION='1' and DMA_WEN='1' then 
				COUNT2 <= COUNT2-1; 
			end if; 
			if DMA_DIRECTION='0' and WR_DMA='1' then 
				COUNT1 <= COUNT1-1; 
			elsif DMA_DIRECTION='1' and RD_DMA='1' then 
				COUNT1 <= COUNT1-1; 
			end if; 
		end if; 
	end if; 
end process; 
 
-- Generate counter outputs and terminal count. 
TERM_CNT <= '1' when (COUNT1=ONE and (WR_DMA='1' or RD_DMA='1')) or COUNT1=ZEROS else '0';	 
COUNT_OUT <= COUNT2 when DMA_DIRECTION='0' else COUNT1; 
DMA_COUNT <= COUNT2;									 
 
end DMA_CTRL_arch;