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

📄 mc8051.vhd

📁 8051 vhdl source code
💻 VHD
📖 第 1 页 / 共 5 页
字号:
    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 wtemp        : wVec;            -- 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   ------------------------------------------------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#8A# THEN               byte_slice := TL0;            ELSIF addr_int = 16#8B# THEN               byte_slice := TH0;            ELSIF addr_int = 16#8C# THEN               byte_slice := TL1;            ELSIF addr_int = 16#8D# THEN               byte_slice := TH1;                        -- TCON            ELSIF addr_int = 16#88# THEN               byte_slice := direct_hi_dmem(addr_int);               byte_slice(7) := TF1;               byte_slice(5) := TF0;               byte_slice(3) := not int1_n_internal;               byte_slice(1) := not int0_n_internal;                        ELSE                byte_slice := direct_hi_dmem(addr_int);            END IF;            RETURN(byte_slice);        END FUNCTION get_byte_dmem;        -- set_acc will set the value of the accumulator and update PSW        PROCEDURE set_acc(            CONSTANT val  : IN bVec        ) IS            variable temp_int: integer;        BEGIN            acc <= val;            -- The parity bit (bit 0 of PSW) is automatically set / cleared            -- to indicate an odd / even number of 1's in acc            temp_int := 0;            FOR k IN acc'RANGE LOOP               temp_int := conv_integer(acc(k)) + temp_int;            END LOOP;            IF (temp_int MOD 2 = 1) THEN                PSW(0) <= '1';            ELSE                PSW(0) <= '0';            END IF;        END PROCEDURE set_acc;        -- 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                lo_dmem(addr_int) <= val;            ELSIF mode = indirect THEN                indirect_hi_dmem(addr_int) <= val;            -- write to sbuf            ELSIF addr_int = 16#99# THEN               addr_gb <= "10011001";               data_gb <= val;               wr_gb <= '1';               WAIT UNTIL acknow = '1';               wr_gb <= 'L';               addr_gb <= "ZZZZZZZZ";               data_gb <= "ZZZZZZZZ";            -- write to scon            ELSIF addr_int = 16#98# THEN               direct_hi_dmem(addr_int) <= val;               addr_gb <= "10011000";               data_gb <= val;               wr_gb <= '1';               WAIT UNTIL acknow = '1';               wr_gb <= 'L';               addr_gb <= "ZZZZZZZZ";               data_gb <= "ZZZZZZZZ";            ELSIF addr_int = 16#8A# THEN               TL0_main <= val;            ELSIF addr_int = 16#8B# THEN               TL1_main <= val;            ELSIF addr_int = 16#8C# THEN               TH0_main <= val;            ELSIF addr_int = 16#8D# THEN               TH1_main <= val;            -- TCON            ELSIF addr_int = 16#88# THEN                direct_hi_dmem(addr_int) <= val;                TF1_main <= val(7);                TF0_main <= val(5);                        -- ACC            ELSIF addr_int = 16#E0# THEN                set_acc(val);                        ELSE                             direct_hi_dmem(addr_int) <= val;            END IF;        END PROCEDURE set_byte_dmem;        -- get_reg will get the value of register (number) based upon        -- the current bank number as defined in register select (rs)        IMPURE FUNCTION get_reg(            CONSTANT number : IN unsigned(2 DOWNTO 0)        ) RETURN bVec IS            VARIABLE addr : bvec;        BEGIN            addr := unsigned'("000") & rs & number;            RETURN get_byte_dmem(addr, direct);         END FUNCTION get_reg;         -- set_reg will set the value of register (number) based upon        -- the current bank number as defined in register select (rs)        PROCEDURE set_reg(            CONSTANT number : IN unsigned(2 DOWNTO 0);            CONSTANT value  : IN bVec        ) IS            VARIABLE addr  : bvec;        BEGIN            addr := unsigned'("000") & rs & number;            set_byte_dmem(addr, value, direct);        END PROCEDURE set_reg;        -- get_bit_dmem will return the value of the bit at bit address (addr)        -- will always use direct mem        IMPURE FUNCTION get_bit_dmem(            CONSTANT addr : IN bVec;            CONSTANT read_latch : IN BOOLEAN := FALSE        ) RETURN std_logic IS            VARIABLE byte_slice : bVec;            VARIABLE addr1      : bVec;             VARIABLE ret_val    : std_ulogic;        BEGIN            IF addr(7) = '0' THEN  -- if addr < 16#80 THEN                addr1 := unsigned'("0010") & addr(6 DOWNTO 3);             ELSIF addr(7) = '1' THEN  -- if addr > 16#80 THEN                addr1 := addr(7 DOWNTO 3) & unsigned'("000");            ELSE                REPORT "8051 Internal Error: Bad address in get_bit_dmem";            END IF;            byte_slice := get_byte_dmem(addr1,direct,read_latch); -- read latch            ret_val := byte_slice(conv_integer(addr(2 DOWNTO 0)));                        -- Check for particular SFRs            IF addr = 16#8F# THEN                ret_val := TF1;            ELSIF addr = 16#8D# THEN                ret_val := TF0;            ELSIF addr = 16#8B# THEN            	ret_val := not int1_n_internal;            ELSIF addr = 16#89# THEN                ret_val := not int0_n_internal;            END IF;                        RETURN(ret_val);        END FUNCTION get_bit_dmem;         -- set_bit_dmem will set the value of the bit at bit address (addr)        -- always assumed to be a "Read Modify Write" instruction, so that        -- setting a bit to the port will read the surrounding bits from the        -- port mirror (latch).        PROCEDURE set_bit_dmem(            CONSTANT addr : IN bvec;            CONSTANT val  : IN std_logic        ) IS            VARIABLE byte_slice : bvec;            VARIABLE addr1      : bvec;         BEGIN            IF addr = 16#D0# THEN                report "Assigning to parity bit has no effect" severity warning;                RETURN;            END IF;                    IF addr(7) = '0' THEN  -- if addr < 16#80 THEN                addr1 := unsigned'("0010") & addr(6 DOWNTO 3);             ELSIF addr(7) = '1' THEN  -- if addr > 16#80 THEN                addr1 := addr(7 DOWNTO 3) & unsigned'("000");            ELSE                REPORT "8051 Internal Error: Bad address in get_bit_dmem";            END IF;            byte_slice := get_byte_dmem(addr1,direct,TRUE); -- read latch            byte_slice(conv_integer(addr(2 DOWNTO 0))) := val;            set_byte_dmem(addr1,byte_slice,direct);                        -- Check for particular SFRs            IF addr = 16#8F# THEN                TF1_main <= val;            ELSIF addr = 16#8D# THEN                TF0_main <= val;            END IF;                    END PROCEDURE set_bit_dmem; -------------------------------------------End of Memory Handling Procdures -------------------------------------------procedure get data        -- This function will get data from either data memory, a register,        -- or direct (from program memory) based on the opcode passed.        -- It uses the following table for the last few digits of the opcode        --    0000, 0001, 0010, 0011   Not found by this procedure!        --    0100  :  Use immediate data in program memory        --    0101  :  Use direct address        --    011i  :  Use data at address contained in register 0 or 1 (i)        --    1rrr  :  Use register rrr        PROCEDURE get_data(            CONSTANT opcode     : IN    bVec;    -- opcode used to select data            VARIABLE data       : INOUT bVec;    -- The 8-bits of data            CONSTANT read_latch : IN    BOOLEAN := FALSE        ) IS            VARIABLE nxt_pmem1  : bVec;          -- Temporary data        BEGIN            IF opcode(3) = '1' THEN           -- use register                data := get_reg(opcode(2 DOWNTO 0));            ELSIF opcode(2 DOWNTO 0) =unsigned'( "101") THEN -- use direct memory                data := get_byte_dmem(pmem_s4_byte, direct, read_latch);            ELSIF opcode(2 DOWNTO 0) =unsigned'( "100") THEN -- use immediate data                data := pmem_s4_byte;            ELSIF opcode(2 DOWNTO 0) =unsigned'( "110") THEN -- use data @R0                data := get_byte_dmem(get_reg("000"),indirect) ;            ELSIF opcode(2 DOWNTO 0) =unsigned'( "111") THEN -- use data @R1                data := get_byte_dmem(get_reg("001"), indirect);            END IF;        END PROCEDURE get_data;         FUNCTION advance_pc(            CONSTANT opcode    : IN    bVec    -- opcode used to select data        ) RETURN INTEGER IS            VARIABLE pc_inc : INTEGER;        BEGIN            IF opcode(3) = '1' THEN           -- use register                pc_inc := 0;            ELSIF opcode(2 DOWNTO 0) =unsigned'( "101") THEN -- use direct memory                pc_inc := 1;            ELSIF opcode(2 DOWNTO 0) =unsigned'( "100") THEN -- use immediate data                pc_inc := 1;

⌨️ 快捷键说明

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