----------------------------------------------------------------------------- -- Intel 8237A DMA controller -- Roman Lysecky -- -- 07/16/1999 -- Version 1.1(Small) -- Notes: The port names follow the 8237A naming except for EOP. -- Due to synthesis problems, EOP has been named eopp. -- This design only provides a small subset of the 8237A. ----------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; ----------------------------------------------------------------------------- entity I8237A is port(clk : in STD_LOGIC; cs : in STD_LOGIC; reset : in STD_LOGIC; ready : in STD_LOGIC; hlda : in STD_LOGIC; dreq : in UNSIGNED(3 downto 0); db : inout UNSIGNED(7 downto 0); ior : inout STD_LOGIC; iow : inout STD_LOGIC; eopp : inout STD_LOGIC; a3_0 : inout UNSIGNED(3 downto 0); a7_4 : out UNSIGNED(3 downto 0); hrq : out STD_LOGIC; dack : out UNSIGNED(3 downto 0); aen : out STD_LOGIC; adstb : out STD_LOGIC; memr : out STD_LOGIC; memw : out STD_LOGIC); end I8237A; ----------------------------------------------------------------------------- architecture BHV_I8237A of I8237A is -- -- type declarations -- subtype INT2 is INTEGER range 0 to 3; subtype REG_16 is UNSIGNED(15 downto 0); subtype REG_8 is UNSIGNED(7 downto 0); subtype REG_6 is UNSIGNED(5 downto 0); subtype REG_4 is UNSIGNED(3 downto 0); type STATE_TYPE is (IDLE, S0, SS1, SSB2, SS2, SS3, SS4); -- -- constant declarations -- constant Z_8 : UNSIGNED(7 downto 0) := "ZZZZZZZZ"; constant Z_4 : UNSIGNED(3 downto 0) := "ZZZZ"; constant C0_16 : UNSIGNED(15 downto 0) := "0000000000000000"; constant C0_8 : UNSIGNED(7 downto 0) := "00000000"; constant CFF_8 : UNSIGNED(7 downto 0) := "11111111"; constant C0_6 : UNSIGNED(5 downto 0) := "000000"; constant C0_4 : UNSIGNED(3 downto 0) := "0000"; constant C1_4 : UNSIGNED(3 downto 0) := "1111"; constant BT : UNSIGNED(1 downto 0) := "10"; -- -- register declarations -- signal curr_addr : REG_16; signal curr_word : REG_16; signal base_addr : REG_16; signal base_word : REG_16; signal command : REG_8; signal mode : REG_6; signal request : REG_4; signal mask : REG_4; -- -- signal declarations -- signal drequest : UNSIGNED(3 downto 0); signal ff : STD_LOGIC; signal mast_clr : STD_LOGIC; signal state : STATE_TYPE; signal channel : INT2; signal adstb_needed : STD_LOGIC; begin drequest(0) <= ((command(6) xor dreq(0)) and not mask(0)) or request(0); drequest(1) <= ((command(6) xor dreq(1)) and not mask(1)) or request(1); drequest(2) <= ((command(6) xor dreq(2)) and not mask(2)) or request(2); drequest(3) <= ((command(6) xor dreq(3)) and not mask(3)) or request(3); process(clk, reset, mast_clr, drequest) begin if ( reset = '1' ) then -- -- steady state -- state <= IDLE; db <= Z_8; ior <= 'Z'; iow <= 'Z'; eopp <= '1'; a3_0 <= Z_4; a7_4 <= Z_4; hrq <= '0'; dack <= "1111"; aen <= '0'; adstb <= '0'; memr <= '0'; memw <= '0'; -- -- reset device -- curr_addr <= C0_16; curr_word <= C0_16; base_addr <= C0_16; base_word <= C0_16; command <= C0_8; mode <= C0_6; request <= C0_4; mask <= C0_4; ff <= '0'; mast_clr <= '0'; channel <= 0; adstb_needed <= '0'; elsif ( mast_clr = '1' ) then -- -- steady state -- state <= IDLE; db <= Z_8; ior <= 'Z'; iow <= 'Z'; eopp <= 'Z'; a3_0 <= Z_4; a7_4 <= Z_4; hrq <= '0'; dack <= C1_4; aen <= '0'; adstb <= '0'; memr <= '0'; memw <= '0'; -- -- reset device -- command <= C0_8; request <= C0_4; mask <= C0_4; ff <= '0'; mast_clr <= '0'; channel <= 0; adstb_needed <= '0'; elsif ( clk'event and clk = '1' ) then -- -- steady state -- state <= IDLE; db <= Z_8; ior <= 'Z'; iow <= 'Z'; eopp <= 'Z'; a3_0 <= Z_4; a7_4 <= Z_4; hrq <= '0'; aen <= '0'; adstb <= '0'; memr <= '0'; memw <= '0'; adstb_needed <= '0'; -- -- output correct acknowledge -- if ( command(7) = '1' ) then dack <= C0_4; elsif( command(7) = '0' ) then dack <= C1_4; else dack <= C1_4; end if; case ( state ) is when IDLE => state <= IDLE; if ( hlda = '0' and drequest /= C0_4 ) then state <= S0; hrq <= '1'; elsif ( hlda = '0' and cs = '0' ) then if( ior = '1' and iow = '0' ) then case( a3_0 ) is when "1000" => command <= db; when "1011" => if ( db(3 downto 2) /= 3 ) then mode <= db(7 downto 2); end if; when "1101" => mast_clr <= '1'; when "0000" => if ( ff = '0' ) then curr_addr(7 downto 0) <= db; base_addr(7 downto 0) <= db; ff <= '1'; else curr_addr(15 downto 8) <= db; base_addr(15 downto 8) <= db; ff <= '0'; end if; when "0001" => if ( ff = '0' ) then curr_word(7 downto 0) <= db; base_word(7 downto 0) <= db; ff <= '1'; else curr_word(15 downto 8) <= db; base_word(15 downto 8) <= db; ff <= '0'; end if; when others => null; end case; elsif( ior = '0' and iow = '1' ) then case( a3_0 ) is when "0000" => if ( ff = '0' ) then db <= curr_addr(7 downto 0); ff <= '1'; else db <= curr_addr(15 downto 8); ff <= '0'; end if; when "0001" => if ( ff = '0' ) then db <= curr_word(7 downto 0); ff <= '1'; else db <= curr_word(15 downto 8); ff <= '0'; end if; when others => null; end case; end if; end if; when S0 => state <= S0; hrq <= '1'; if ( drequest(channel) = '0' ) then state <= IDLE; elsif ( hlda = '1' ) then state <= SS1; end if; if ( hlda = '0' and cs = '0' ) then state <= S0; if( ior = '1' and iow = '0' ) then case( a3_0 ) is when "1000" => command <= db; when "1011" => if ( db(3 downto 2) /= 3 ) then mode <= db(7 downto 2); end if; when "1101" => mast_clr <= '1'; when others => null; end case; end if; end if; when SS1 => state <= SS2; hrq <= '1'; if ( drequest(channel) = '0' ) then state <= IDLE; else aen <= '1'; end if; when SS2 => state <= SS3; hrq <= '1'; if ( drequest(channel) = '0' ) then state <= IDLE; else aen <= '1'; adstb <= '1'; db <= curr_addr(15 downto 8); a7_4 <= curr_addr(7 downto 4); a3_0 <= curr_addr(3 downto 0); dack(channel) <= command(7); case ( mode(1 downto 0) ) is when "00" => null; when "01" => ior <= '1'; memw <= '1'; when "10" => iow <= '1'; memr <= '1'; when others => null; end case; end if; when SSB2 => state <= SS3; hrq <= '1'; aen <= '1'; if( adstb_needed = '1' ) then adstb <= '1'; db <= curr_addr(15 downto 8); end if; a7_4 <= curr_addr(7 downto 4); a3_0 <= curr_addr(3 downto 0); dack(channel) <= command(7); case ( mode(1 downto 0) ) is when "00" => null; when "01" => ior <= '1'; memw <= '1'; when "10" => iow <= '1'; memr <= '1'; when others => null; end case; when SS3 => state <= SS4; hrq <= '1'; aen <= '1'; a7_4 <= curr_addr(7 downto 4); a3_0 <= curr_addr(3 downto 0); dack(channel) <= command(7); case ( mode(1 downto 0) ) is when "00" => null; when "01" => ior <= '0'; memw <= '0'; when "10" => iow <= '0'; memr <= '0'; when others => null; end case; when SS4 => state <= IDLE; hrq <= '1'; aen <= '1'; a7_4 <= curr_addr(7 downto 4); a3_0 <= curr_addr(3 downto 0); dack(channel) <= command(7); case ( mode(1 downto 0) ) is when "00" => null; when "01" => ior <= '0'; memw <= '0'; when "10" => iow <= '0'; memr <= '0'; when others => null; end case; if( curr_word = C0_16 ) then if( mode(2) = '1' ) then curr_word <= base_word; curr_addr <= base_addr; elsif( mode(2) = '0' ) then curr_word <= curr_word - 1; if( mode(3) = '0' ) then curr_addr <= curr_addr + 1; elsif( mode(3) = '1' ) then curr_addr <= curr_addr - 1; end if; end if; else curr_word <= curr_word - 1; if( mode(3) = '0' ) then if( curr_addr(7 downto 0) = CFF_8) then adstb_needed <= '1'; end if; curr_addr <= curr_addr + 1; elsif( mode(3) = '1' ) then if( curr_addr(7 downto 0) = C0_8) then adstb_needed <= '1'; end if; curr_addr <= curr_addr - 1; end if; if( mode(5 downto 4) = BT ) then state <= SSB2; else state <= IDLE; end if; end if; when others => null; end case; end if; end process; end BHV_I8237A; -----------------------------------------------------------------------------