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

📄 mc8051.vhd

📁 8051 vhdl source code
💻 VHD
📖 第 1 页 / 共 5 页
字号:
            ELSIF opcode(2 DOWNTO 0) =unsigned'( "110") THEN -- use data @R0                pc_inc := 0;            ELSIF opcode(2 DOWNTO 0) =unsigned'( "111") THEN -- use data @R1                pc_inc := 0;            END IF;            RETURN pc_inc;        END FUNCTION advance_pc;  -------------------------------------------procedure handle add        -- This function handles the carry's and adding for the ADD and ADDC         -- opcodes.        PROCEDURE handle_add(            CONSTANT opcode : IN    bVec;   -- The opcode, used to select the 2nd operand            CONSTANT cy_in  : IN    std_logic  -- set to '0' for ADD, cy for ADDC         ) IS            VARIABLE operand2   : bVec;     -- the 2nd operand            VARIABLE new_sum    : INTEGER;  -- the new sum to be put in the acc            VARIABLE pc_inc     : INTEGER;  -- amount to increment pc       BEGIN            pc <= pc + 1 + advance_pc(opcode);            WAIT UNTIL cycle_state = s5p1;            get_data(opcode, operand2);            new_sum := conv_integer(acc) + conv_integer(operand2) + conv_integer(cy_in);            -- Set carry flag if there is a carry out of bit 7            IF new_sum > 255 THEN                cy <= '1';            ELSE                cy <= '0';            END IF;            -- Set aux. carry flag if there is a carry out of bit 3            IF (conv_integer(acc(3 DOWNTO 0))+conv_integer(operand2(3 DOWNTO 0))+                conv_integer(cy_in)) > 15 THEN                ac <= '1';            ELSE                ac <= '0';            END IF;            -- Set OV if there is a carry from bit 6 but not bit 7, or            -- if there is a carry from 7 but none from 6.  Otherwise, clear.            IF conv_integer(acc(6 DOWNTO 0))+conv_integer(operand2(6 DOWNTO 0)) > 127 THEN                                       -- There is a carry from 6               IF new_sum > 255 THEN   -- and from 7                  ov <= '0';           -- so clear overflow               ELSE                    -- If there is not a carry from 7,                  ov <= '1';           -- then set overflow               END IF;            ELSE                       -- If there is not a carry from 6               IF NEW_sum > 255 THEN   -- and there is from 7                  ov <= '1';           -- set overflow.                ELSE                    -- If there is not a carry from 7,                  ov <= '0';           -- then clear overflow               END IF;            END IF;            -- Finally, put the new sum into the acc (getting rid of any overflow)            acc <= conv_unsigned(new_sum, 8);        END PROCEDURE handle_add; -------------------------------------------procedure handle sub        -- This function handles the carry's and subtracting for the SUBB opcode        PROCEDURE handle_sub(            CONSTANT opcode : IN    bVec   -- The opcode, used to select the 2nd operand        ) IS            VARIABLE acc_int,op2_int,cy_int : INTEGER;-- bits converted to int            VARIABLE operand2  : bVec;                -- the 2nd operand            VARIABLE new_diff  : INTEGER;             -- the new diff for acc        BEGIN            pc <= pc + 1 + advance_pc(opcode);            WAIT UNTIL cycle_state = s5p1;            get_data(opcode, operand2);            acc_int := conv_integer(acc);            op2_int := conv_integer(operand2);            cy_int  := conv_integer(cy);            IF acc_int >= op2_int + cy_int THEN               new_diff := acc_int - (op2_int + cy_int);               cy <= '0';  -- clear cy (borrow) flag            ELSE               -- If the subtractants are larger than the acc, set               -- borrow and add 256 to acc               new_diff := (acc_int + 256) - (op2_int + cy_int);               cy <= '1';  -- set cy (borrow) flag            END IF;            -- Set OV if there is borrow into bit 6 but not bit 7, or            -- into bit 7 but not bit 6.  Otherwise, clear.            IF conv_integer(acc(6 DOWNTO 0)) <               conv_integer(operand2(6 DOWNTO 0)) + cy_int THEN                                -- There is a borrow into bit 6               IF acc_int >= op2_int + cy_int THEN                                -- but not into bit 7                  ov <= '1';    -- so set ov (overflow)               ELSE             -- There is not a borrow into bit 7                  ov <= '0';    -- so clear overflow               END IF;            ELSE                -- There is not a borrow into bit 6               IF acc_int >= op2_int + cy_int THEN                                -- and not into 7                  ov <= '0';    -- then clear overflow               ELSE             -- There is a borrow into bit 7                  ov <= '1';    -- So set overflow               END IF;            END IF;            -- Set AC if there is a borrow into bit 3, otherwise reset it            IF conv_integer(acc(3 DOWNTO 0)) <               conv_integer(operand2(3 DOWNTO 0)) + cy_int THEN                ac <= '1';            ELSE                ac <= '0';            END IF;            acc <= conv_unsigned(new_diff, 8);        END PROCEDURE handle_sub;		-- resolve2 resolves two signals into one	-- Used for SFRs written to by processes other than main	PROCEDURE resolve2 (signal first, second: in bvec; 	                    signal output: out bvec) IS	BEGIN	   if second'event then	      output <= second;	   end if;	   if first'event then	      output <= first;	   end if;	END PROCEDURE resolve2;	PROCEDURE resolve2 (signal first, second: in std_logic; 	                    signal output: out std_logic) IS	BEGIN	   if second'event then	      output <= second;	   end if;	   if first'event then	      output <= first;	   end if;	END PROCEDURE resolve2;         -- 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            set_byte_dmem("10110000", "11111111", direct);            ie <= "00000000";            ip <= "00000000";            tmod <= "00000000";            pcon <= "00000000";     --     scon, tcon, th0, th1, tl0, tl1            -- SCON            set_byte_dmem("10011000", "00000000", direct);            -- TCON            set_byte_dmem("10001000", "00000000", direct);            -- TH0            set_byte_dmem("10001100", "00000000", direct);            -- TH1            set_byte_dmem("10001101", "00000000", direct);            -- TL0            set_byte_dmem("10001010", "00000000", direct);            -- TL1            set_byte_dmem("10001011", "00000000", direct);        END PROCEDURE set_sfr; ------------------------------------------- Begin the Process main        --VARIABLE first_inst : BOOLEAN := TRUE;    BEGIN  -- process main     -- There are six states to a machine cycle, some commands take    -- more than one cycle.  However, here is the general timing    -- State 1 Pulse 1 - The opcode is read in by the get_pmem process    -- State 1 Pulse 2 - The next address (pc + 1) is stored for output    --                   by the get_pmem process    -- State 2 Pulse 1 - Process main reads the opcode and decodes it.    --                   pc is updated if it is a one cycle code    --                   the operation is completed if no more data required    -- State 4 Pulse 1 - The next data (at pc + 1) is read in by get_pmem    -- State 4 Pulse 2 - If pc was updated, the new pc addr is stored by    --                   process get_pmem.  Otherwise, addr for pc + 2 is    --                   stored.    -- State 5 Pulse 1 - The new pmem data (s4p1) is read by process main, if    --                   necessary, and operations performed.  pc updated    --    -- Last cycle of a multi-cycle opcode:    -- State 1 Pulse 1 - The pc has not been changed since this opcode    --                   was deciphered, so the next byte of pmem (at pc + 2)    --                   is read by process get_pmem.    -- State 1 Pulse 2 - The next address (pc + 3) is stored for later use    --                   in process get_pmem.    -- State 2 Pulse 1 - The byte of s1p1 is read in by process main, and    --                   any operations performed    --                   pc is now updated    -- State 4 Pulse 1 - The next data (pc + 4) is read by process get_pmem    -- State 4 Pulse 2 - The new pc is read and stored for output.    -- State 5 Pulse 1 - The opcode should be done by now!         -- rst = 'U' handles case where we start up in reset mode, but         -- the processor hasn't detected that yet        IF rst = '1' or rst = 'H' or rst = 'U' THEN            init_gb <= FALSE;            init_done := FALSE;            WAIT UNTIL rst = '0';        END IF;        -- set init values        IF NOT init_done THEN            set_sfr;            reset_pmem <= '1';            pc <= "0000000000000000";            -- Set any signals driven from this process to 'Z'            p0_addr <= "ZZZZZZZZ";            p2_addr <= "ZZZZZZZZ";            p0_ctrl <= 'Z';            p2_ctrl <= 'Z';            rd_n_internal <= '1';            wr_n_internal <= '1';            WAIT UNTIL cycle_state = s4p1;            init_done := TRUE;            init_gb <= TRUE;            reset_pmem <= '0';        END IF;        WAIT UNTIL cycle_state = s2p1;        -- When a data / addr value is written to P0, then it is        -- reset to all 1's.  The get_pmem process cannot do that        -- by itself, so we will implement that here.        IF p0_reset = '1' THEN            p0_latch <= "11111111";            p0_reset_ack <= '1';        END IF;        IF p0_reset = '0' THEN            p0_reset_ack <= '0';        END IF;        -- 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;         ------------INTERRUPTS------------------        -- Check to see if an interrupt needs to be processed        -- Only check for serial at the moment            -- determine the new PC in order of same-level priority            -- and set the new processor priority depending upon            -- IP register setting            IF ea = '1' AND (en_x0 = '1' AND int0_n_internal = '0') AND   -- ext 0                  (current_priority = "00" OR                   (current_priority = "01" AND IP(0) = '1')) THEN                   -- LCALL                   WAIT UNTIL cycle_state = s2p1;   -- wait for next cycle                   temp_pc := pc;                   set_byte_dmem(sp + 1, temp_pc(7 DOWNTO 0), indirect);                   set_byte_dmem(sp + 2, temp_pc(15 DOWNTO 8), indirect);                   sp <= sp + 2;  -- update stack pointer to point to the new data                   previous_priority <= current_priority;                   current_priority(1) <= IP(0);                   current_priority(0) <= '1';                   pc <= "0000000000000011";   -- 03                   WAIT UNTIL cycle_state = s4p1;            ELSIF ea = '1' AND (en_t0 = '1' AND TF0 = '1')   AND  -- timer 0                  (current_priority = "00" OR                   (current_priority = "01" AND IP(1) = '1')) THEN                   -- LCALL                   WAIT UNTIL cycle_state = s2p1;   -- wait for next cycle                   temp_pc := pc;                   set_byte_dmem(sp + 1, temp_pc(7 DOWNTO 0), indirect);                   set_byte_dmem(sp + 2, temp_pc(15 DOWNTO 8), indirect);                   sp <= sp + 2;  -- update stack pointer to point to the new data                   previous_priority <= current_priority;                   current_priority(1) <= IP(1);                   current_priority(0) <= '1';                   pc <= "0000000000001011";   -- 0B                   -- Interrupt flag cleared in hardware                   TF0_main <= '0';                   WAIT UNTIL cycle_state = s4p1;            ELSIF ea = '1' AND (en_x1 = '1' AND int1_n_internal = '0') AND  -- ext 1                  (current_priority = "00" OR                   (current_priority = "01" AND IP(2) = '1')) THEN                   -- LCALL                   WAIT UNTIL cycle_state = s2p1;   -- wait for next cycle                   temp_pc := pc;                   set_byte_dmem(sp + 1, temp_pc(7 DOWNTO 0), indirect);                   set_byte_dmem(sp + 2, temp_pc(15 DOWNTO 8), indirect);                   sp <= sp + 2;  -- update stack pointer to point to the new data                   previous_priority <= current_priority;

⌨️ 快捷键说明

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