⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i8237a.vhd

📁 经典DMA控制器8237A的VHDL设计
💻 VHD
字号:
------------------------------------------------------------------------------- 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;-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -