--**********************************************************************

--  - H/W Development Group

-- ************************************************************************

--

--  Title:     BASIC DAM CONTROLLER

--

--  Created:   Fri Aug 25 17:58:34 2000

--  Author:    DEEPAK GEORGE

--  Source File Name:   dma.vhd

--

--  $Id: dma.vhd,v 1.1 2000/08/25 17:58:34 acts Exp $

--

--  Description:  This file give the vhdl code for a basic DMA controller

--                connected to only one peripheral IO device.

--

--  Revision History: Rev 1.0  2000/08/28 5:38PM

--                    Rev 2.0  2000/08/29 10:45AM

--

--  $Log: dma.vhd $

--

-- ************************************************************************

 

library IEEE, STD;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_components.all;

use IEEE.std_logic_arith.all;

use IEEE.std_logic_misc.all;

use IEEE.std_logic_unsigned.all;

 

 

entity dma is

  port     (clk              : in   std_logic;--   Clock

            rst              : in   std_logic;--   Reset

            dma_rq           : in   std_logic;--   DMA Request from peripheral

            HLDA             : in   std_logic;--   HOLD ACK from uP.

            rd_b             : in   std_logic;--   Read

            wr_b             : in   std_logic;--   Write

            D_rdy            : in   std_logic;--   Indicates Status of IO Device

            count            : in   std_logic_vector(7 downto 0);-- Count input

            addrin           : in   std_logic_vector(7 downto 0);-- Addr. input

            hold             : out  std_logic;--   HOLD to uP

            dma_ack          : out  std_logic;--   To peripheral

            Memr_b           : out  std_logic;--   Memory Read

            Memw_b           : out  std_logic;--   Memory Write

            ior_b            : out  std_logic;--   IO read

            iow_b            : out  std_logic;--   IO write

            TC               : out  std_logic;--   Terminal Count

            addrout          : out  std_logic_vector(7 downto 0) --   Addr. out.

          );

end dma;

architecture dma_A of dma is

  type state_t is (s0,s1,s2,s3,s4);

  signal state : state_t;  

  signal counti           : std_logic_vector(7 downto 0);

  signal addri            : std_logic_vector(7 downto 0);

  --   stores the count and  address on getting a DMA request

 

  signal rd_bi            : std_logic;

  signal wr_bi            : std_logic;

  --   Stores the status of Read and Write signal at the time of DMA req.

   

begin

  main : process(clk,rst)

  

  begin

      addri   <= (others =>'0');

      counti  <= (others =>'0');

      hold    <= '0';

      dma_ack <= '0';

      Memw_b  <= '1';

      ior_b   <= '1';

      Memr_b  <= '1';

      iow_b   <= '1';

      Tc      <= '0';

      state   <= s0 ;

      addr_out<= (others=>'Z');

    elsif (clk'event and clk = '1') then

      case state  is

        when s0 =>

          if (dma_rq = '1') then                  -- Check for DMA Request  

            hold  <= '1';                         -- Issue HOLD  

            addri <= addrin;                      -- Store Addr in addr reg  

            counti<= count;                       -- Store Count in count reg  

            rd_bi <= rd_b;                        -- Store RD signal 

            wr_bi <= wr_b;                        -- Store WR signal  

            state <= s1;

          end if;

        when s1 =>

          if(hlda = '1') then                     -- Check for Hold Ack  

            dma_ack  <= '1';

            state    <= s2 ;

          end if;

         

         when s2 =>

            if ( D_rdy = '1') then                  -- Checks Status of IO Device

              if (rd_bi='0' and wr_bi='1') then     -- Memory Read IO Write Operation 

                Memr_b <= '0';

                iow_b  <= '0';

                Memw_b <= '1';

                ior_b  <= '1';

                state  <=  s3;

              elsif (rd_bi='1' and wr_bi='0') then  -- IO Read Memory Write Operation  

                Memr_b <= '1';

                iow_b  <= '1';

                Memw_b <= '0';

                ior_b  <= '0';

                state  <=  s3;

              end if;

            end if; 

         

        when s3 =>                             --   Reset the R\W signals  

          Memw_b <= '1';

          ior_b  <= '1';

          Memr_b <= '1';

          iow_b  <= '1';

          state  <= s4 ;

       

        when s4 =>

          if (counti<="00000000") then         --   Checks for Terminal Count,if

            tc     <= '1';                     --   reached gives TC = '1' and

            hold   <= '0';                     --   deactivates the hold and waits

            dma_ack<= '0';                     --   for the next DMA request to  

                                               --   appear.

            state  <= s0 ;

          else                                 --   If terminal count not reached

            counti <= counti - 1;              --   then decriment the counter by

            addri  <= addri +  1;              --   1 and incriment the addr by 1

            tc     <= '0';

            state  <= s1 ;

         end if; 

      end case;

    end if;

  end process;

---------------------------------------------------------------------------

--  Output the address when Hold Ack is 1 and Device ready is 1, else

--  tristate the address bus.

---------------------------------------------------------------------------

addrout <= addri when (D_Rdy = '1' and Hlda = '1') else

           "ZZZZZZZZ";

end dma_A;