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

📄 mc8051.vhd

📁 8051的VHDL IP核
💻 VHD
📖 第 1 页 / 共 5 页
字号:
              std_logic_vector(p0_addr)  WHEN p0_ctrl = '1' ELSE               std_logic_vector(to_high_imped(p0_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P1    <= (OTHERS => 'Z') WHEN rst = '1' ELSE               std_logic_vector(to_high_imped(p1_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P2    <= (OTHERS => 'Z')             WHEN rst = '1' ELSE               std_logic_vector(p2_addr)  WHEN p2_ctrl = '1' ELSE              std_logic_vector(to_high_imped(p2_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P3    <= (OTHERS => 'Z') WHEN rst = '1' ELSE               std_logic_vector(to_high_imped(p3_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    -- always enable the UART for mode 2--    p3_ctrl(0) <= 'Z';--    P3(0)  <= rxd_internal WHEN p3_ctrl(0) = '1' ELSE 'Z';    p3_ctrl(1) <= '1';    rxd_internal <= P3(0);    P3(1)  <= txd_internal WHEN p3_ctrl(1) = '1' AND rst = '0' ELSE 'Z';    -- whenever there is a falling edge on the interrupt pin, it will    -- be sent to the interrupt processor (which may acknowledge or mask)    -- for a level sensitive interrupt (it? = 0) the rising edge of the pin    -- will clear out this internal signal.  For an edge sensitve interrupt    -- (it? = 1) the acknowledge from the interrupt processor will clear    int0_n_internal <= '0' WHEN falling_edge(p3(2)) ELSE                       '1' WHEN rising_edge(p3(2)) AND it0 = '0' ELSE                       '1' WHEN interrupt_ack = '1' AND it0 = '1' ELSE                       int0_n_internal;    int1_n_internal <= '0' WHEN falling_edge(p3(3)) ELSE                       '1' WHEN rising_edge(p3(3)) AND it1 = '0' ELSE                       '1' WHEN interrupt_ack = '1' AND it1 = '1' ELSE                       int1_n_internal;    t0_internal <= P3(4);    t1_internal <= P3(5);    P3(6)  <= wr_n_internal WHEN p3_ctrl(6) = '1' AND rst = '0' ELSE 'Z';    P3(7)  <= rd_n_internal WHEN p3_ctrl(7) = '1' AND rst = '0' ELSE 'Z';     --===============================================================    --    Process Statements    --===============================================================    ------------------------------------------------------------------------    -- The oscillator process will follow the XTAL clock signal and    -- advance the current state.  The states are s1p1, s1p2, s2p1, s2p2,    -- up to s6p1 and s6p2.    ------------------------------------------------------------------------    oscillator : PROCESS (XTAL1) IS        VARIABLE last_falling_edge_time : TIME    := 0 ns;        VARIABLE startup_count          : INTEGER := 0;    BEGIN        IF falling_edge(XTAL1) THEN            IF startup_count < 3 THEN                cycle_state <= init;                startup_count := startup_count + 1;                last_falling_edge_time := NOW;            ELSE                cycle_state <= inc(cycle_state);  -- increment the current state,                -- and loop back from s6p2 to s1p1                TCLCL <= NOW - last_falling_edge_time;                last_falling_edge_time := NOW;            END IF;        END IF;    END PROCESS oscillator;     ------------------------------------------------------------------------    -- The process get_pmem is responsible for reading all of the program    -- memory (whetere internal or external) and feeding the read bytes to    -- the process main through the signals pmem_s1_byte and pmem_s4_byte.    -- If there has been a transaction on pc, this process will set    -- its internal addr to the value of pc at state s4p1.  Then, if needed,    -- it will output this addr at s5p1 and then read in the appropriate data    -- at s1p1.  Then it increments its internal addr and will read the next    -- byte at s4p1.  It will continue to increment the internal addr until    -- there is another transaction on pc.    -------------------------------------------------------------------------    get_pmem : PROCESS(cycle_state, pc'TRANSACTION) IS        VARIABLE addr        : INTEGER := 0;        VARIABLE pmem        : program_mem_T;     -- the program memory        VARIABLE prog_loaded : BOOLEAN := FALSE;  -- true after pmem is updated        VARIABLE resync      : BOOLEAN := FALSE;  -- set true when pc changes        VARIABLE port_to_01  : bit_vector(7 DOWNTO 0);     BEGIN        -- Put lines at HiZ if the processor is in reset state        IF rst = '1' THEN            psen_n <= 'Z';            ale_pm <= 'Z';            p0_ctrl <= 'Z';            p2_ctrl <= 'Z';            p0_addr <= "ZZZZZZZZ";            p2_addr <= "ZZZZZZZZ";        ELSIF NOT prog_loaded THEN            IF (ea_n = '1' or ea_n = 'H') THEN                load_program(program_filename,pmem);            END IF;            -- Set default values for control lines            psen_n <= '1';            p0_ctrl <= 'Z';            p2_ctrl <= 'Z';            p0_reset <= '0';            prog_loaded := TRUE;        ELSE            -- If process main has acknowledged a reset, then            -- clear the p0 reset line.            IF p0_reset_ack <= '1' THEN                p0_reset <= '0';            END IF;            -- If there has been a transaction on pc, and it is            -- not the initial start-up state, then flag the            -- resync variable            IF pc'ACTIVE THEN                resync := TRUE;            END IF;            -- If the process main is trying to read a data byte            -- from external mem, yield to it by putting ctrl's            -- to high impedance           IF port_req = '1' THEN                psen_n <= '1';                ale_pm <= '0';                p0_ctrl <= 'Z';                p2_ctrl <= 'Z';                p0_addr <= "ZZZZZZZZ";                p2_addr <= "ZZZZZZZZ";            ELSIF reset_pmem = '1' THEN                resync := TRUE;                addr := 0;            ELSIF cycle_state'ACTIVE THEN                CASE cycle_state IS                WHEN init =>                    NULL;                WHEN s1p1 =>                -- read in the current byte from pmem                    IF ( addr > 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        IF Is_X(P0) THEN                           pmem_s1_byte <= unsigned'("00000000");                            bad_data <= '1';                        ELSE                           port_to_01 := to_bitVector(P0);                           pmem_s1_byte <= unsigned(to_stdlogicvector(port_to_01));                           bad_data <= '0';                        END IF;                    ELSE -- fetch from internal memory                        pmem_s1_byte <= pmem(addr);                    END IF;                WHEN s4p1 =>                -- read in the current byte from pmem                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        port_to_01 := to_bitVector(P0);                        pmem_s4_byte <= unsigned(to_stdlogicvector(port_to_01));                    ELSE -- fetch from internal memory                        pmem_s4_byte <= pmem(addr);                    END IF;                WHEN s1p2 | s4p2 =>                    IF resync THEN                        addr := conv_integer(pc);                        resync := FALSE;                    ELSE                        addr := addr + 1;                    END IF;                    -- strobe ale if next addr is external                    -- rewrite p0_latch to all 1's                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        ale_pm <= '1';                        psen_n <= '1';                        p0_reset <= '1';                    END IF;                WHEN s2p1 | s5p1 =>                -- drive port 0 and port 2 if addr is external                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        p0_addr <= conv_unsigned(addr MOD 256, 8);                        p2_addr <= conv_unsigned(addr / 256, 8);                        p0_ctrl <= '1';                        p2_ctrl <= '1';                    ELSE                        p0_ctrl <= 'Z';                        p2_ctrl <= 'Z';                    END IF;                WHEN s2p2 | s5p2 =>  -- drive ale to zero                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        ale_pm <= '0';                    END IF;                WHEN s3p1 | s6p1 => -- drive psen low                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        psen_n <= '0';                        p0_addr <= "ZZZZZZZZ";                    END IF;                WHEN s3p2  | s6p2 =>                    NULL;                END CASE;            END IF;        END IF;     END PROCESS get_pmem;    ------------------------------------------------------------------------    -- This is the main process of the microcomputer.  It will check the    -- opcode and perform the action.    ------------------------------------------------------------------------    main : PROCESS         VARIABLE opcode       : bVec;            -- the opcode for this cycle        VARIABLE temp1, temp2 : bVec;            -- temp use only        VARIABLE temp_int     : INTEGER;         -- temp use only        VARIABLE temp_pc      : wVec;            -- temp pc storage        VARIABLE init_done    : BOOLEAN := FALSE;        -- set to true once the initializing is done in the first cycle        VARIABLE ie_stored    : bVec;        -- stores ie reg when servicing an interrupt        VARIABLE pc_int       : INTEGER;     -- only used for report         -- set_sfr (set the default value of the special function registers)        PROCEDURE set_sfr IS        BEGIN            acc     <= "00000000";            b       <= "00000000";            psw     <= "00000000";            sp      <= "00000111";            dpl     <= "00000000";            dph     <= "00000000";            p0_latch  <= "11111111";            p1_latch  <= "11111111";            p2_latch  <= "11111111";            p3_latch  <= "11111111";            ie <= "00000000";            ip <= "00000000";     --       pcon <= "00000000";     --     scon, tcon, th0, th1, tl0, tl1, tmod         END PROCEDURE set_sfr;  ------------------------------------------------Memory Handling Procedures        -- Note that the following impure functions and procedures all use        -- the program and/or data memory which is defined as a signal.        -- However, when reading from addr's 80,90,A0,B0 for some will        -- read the port directly, while others will read the ram mirror.        -- Those that read the mirror (latch) are ANL, ORL, XRL, JBC,        -- CPL, INC, DEC, DJNZ, MOV PX.Y, CLR PX.Y, SETB PX.Y         -- get_byte_dmem will return the value of the byte at byte address        -- depending upon if direct or indirect addressing is being used.        -- it will also check if an event has occured on a serial control        -- or buffer and will copy that into the ram        IMPURE FUNCTION get_byte_dmem(            CONSTANT addr : IN bvec;            CONSTANT mode : IN access_type;            CONSTANT read_latch : IN BOOLEAN := FALSE        ) RETURN bvec IS            VARIABLE addr_int   : INTEGER;            VARIABLE byte_slice : bVec;        BEGIN            addr_int := conv_integer(addr);            IF addr_int < 128 THEN                byte_slice := lo_dmem(addr_int);            ELSIF mode = indirect THEN                byte_slice := indirect_hi_dmem(addr_int);            ELSIF (NOT read_latch) AND (addr_int=16#80#) THEN -- read the port itself                byte_slice := unsigned(P0);            ELSIF (NOT read_latch) AND (addr_int=16#90#) THEN -- read the port itself                byte_slice := unsigned(P1);            ELSIF (NOT read_latch) AND (addr_int=16#A0#) THEN -- read the port itself                byte_slice := unsigned(P2);            ELSIF (NOT read_latch) AND (addr_int=16#B0#) THEN -- read the port itself                byte_slice := unsigned(P3);            -- read from sbuf            ELSIF addr_int = 16#99# THEN               byte_slice := sbuf_dup;            ELSIF addr_int = 16#98# THEN               byte_slice := scon_out;--            ELSIF addr_int = 16#98# THEN--               byte_slice := ad_data;-- IF MORE SFR's need to be added, place the READS here in the form above-- ELSIF addr_int = 16#(desired addresss)# THEN--    byte_slice := (data_valute);            ELSE                byte_slice := direct_hi_dmem(addr_int);            END IF;            RETURN(byte_slice);        END FUNCTION get_byte_dmem;        -- set_byte_dmem will set the value of the byte at address (addr)        -- using the appropriate memory for direct / indirect accessing.        PROCEDURE set_byte_dmem(            CONSTANT addr : IN bvec;            CONSTANT val  : IN bVec;            CONSTANT mode : IN access_type        ) IS            VARIABLE addr_int   : INTEGER;        BEGIN            addr_int := conv_integer(addr);            IF addr_int < 128 THEN

⌨️ 快捷键说明

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