📄 mc8051.vhd
字号:
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;
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 int1_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 timer0_int = '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
WAIT UNTIL cycle_state = s4p1;
ELSIF ea = '1' AND (en_x1 = '1' AND int0_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;
current_priority(1) <= IP(2);
current_priority(0) <= '1';
pc <= "0000000000010011"; -- 13
WAIT UNTIL cycle_state = s4p1;
ELSIF ea = '1' AND (en_t1 = '1' AND timer1_int = '1') AND -- timer 1
(current_priority = "00" OR
(current_priority = "01" AND IP(3) = '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(3);
current_priority(0) <= '1';
pc <= "0000000000011011"; -- 1B
WAIT UNTIL cycle_state = s4p1;
ELSIF ea = '1' AND (en_serial = '1' AND (trans_int = '1' OR recv_int = '1')) AND
(current_priority = "00" OR
(current_priority = "01" AND IP(4) = '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(4);
current_priority(0) <= '1';
pc <= "0000000000100011"; -- 23
WAIT UNTIL cycle_state = s4p1;
ELSE -- NO INTERRUPTS
-- Read in the next opcode (at s2p1)
opcode := pmem_s1_byte;
IF bad_data = '1' THEN
pc_int := conv_integer(pc);
REPORT "ERROR: COULD NOT READ OPCODE - X's read from memory. PC is " &
integer'image(pc_int) & "d"
SEVERITY error;
END IF;
-- The opcode is converted to an 8bit integer
CASE smallint(conv_integer(opcode)) IS
-- ACALL: absolute call
WHEN 16#11# | 16#31# | 16#51# | 16#71# | 16#91# | 16#B1# | 16#D1# | 16#F1# =>
--cycle cycles := 2;
pc <= pc + 2;
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
set_byte_dmem(sp + 1, pc(7 DOWNTO 0), indirect);
set_byte_dmem(sp + 2, pc(15 DOWNTO 8), indirect);
sp <= sp + 2;
pc <= pc(15 DOWNTO 11) & opcode(7 DOWNTO 5) & pmem_s4_byte;
-- AJMP: Absolute Jump
WHEN 16#01# | 16#21# | 16#41# | 16#61# | 16#81# | 16#A1# | 16#C1# | 16#E1# =>
--cycle cycles := 2;
pc <= pc + 2;
WAIT UNTIL cycle_state = s2p1; -- wait for the next cycle
pc <= pc(15 DOWNTO 11) &
opcode(7 DOWNTO 5) & pmem_s4_byte;
-- NOP: No operation
WHEN 16#00# =>
--cycle cycles := 1;
pc <= pc + 1;
-- MOV A, Rn
WHEN 16#E8# to 16#EF# =>
--cycle cycles := 1;
pc <= pc + 1;
acc <= get_reg(opcode(2 DOWNTO 0));
-- MOV A, data addr
WHEN 16#E5# =>
--cycle cycles := 1;
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1;
acc <= get_byte_dmem(pmem_s4_byte, direct);
-- MOV A, @Ri
WHEN 16#E6# TO 16#E7# =>
--cycle cycles := 1;
pc <= pc + 1;
temp1 := get_reg("00"&opcode(0)); -- indirect src addr
acc <= get_byte_dmem(temp1, indirect);
-- MOV A, #data
WHEN 16#74# =>
--cycle cycles := 1;
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1;
acc <= pmem_s4_byte;
-- MOV Rn, A
WHEN 16#F8# TO 16#FF# =>
--cycle cycles := 1;
pc <= pc + 1;
set_reg(opcode(2 DOWNTO 0), acc);
-- MOV Rn, data addr
WHEN 16#A8# TO 16#AF# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait to next cycle
pc <= pc + 2;
temp1 := get_byte_dmem(pmem_s4_byte, direct); -- src data
set_reg(opcode(2 DOWNTO 0), temp1); -- set to reg.
-- MOV Rn, #data
WHEN 16#78# TO 16#7F# =>
--cycle cycles := 1;
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1;
set_reg(opcode(2 DOWNTO 0), pmem_s4_byte);
-- MOV data addr, A
WHEN 16#F5# =>
--cycle cycles := 1;
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1;
set_byte_dmem(pmem_s4_byte, acc, direct);
-- MOV data addr, Rn
WHEN 16#88# TO 16#8F# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait to next cycle
pc <= pc + 2;
temp1 := get_reg(opcode(2 DOWNTO 0)); -- src data from Rn
set_byte_dmem(pmem_s4_byte, temp1, direct);
-- MOV direct, direct
WHEN 16#85# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
pc <= pc + 3;
temp1 := get_byte_dmem(pmem_s4_byte, direct); -- the data at source addr
set_byte_dmem(pmem_s1_byte, temp1, direct); -- set to dest addr
-- MOV direct, @Ri
WHEN 16#86# TO 16#87# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
pc <= pc + 2;
temp1 := get_reg("00" & opcode(0)); -- indirect src addr
temp2 := get_byte_dmem(temp1, indirect); -- src data at addr @Ri
set_byte_dmem(pmem_s4_byte, temp2, direct);
-- MOV direct, #data
WHEN 16#75# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
pc <= pc + 3;
set_byte_dmem(pmem_s4_byte, pmem_s1_byte, direct);
-- MOV @Ri, A
WHEN 16#F6# TO 16#F7# =>
--cycle cycles := 1;
pc <= pc + 1;
temp1 := get_reg("00"&opcode(0)); -- indirect dest addr
set_byte_dmem(temp1, acc, indirect);
-- MOV @Ri, direct
WHEN 16#A6# TO 16#A7# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait for the next cycle
pc <= pc + 2;
temp1 := get_reg("00"&opcode(0)); -- the indirect dest addr
temp2 := get_byte_dmem(pmem_s4_byte, direct); -- the src byte
set_byte_dmem(temp1, temp2, indirect);
-- MOV @Ri, #data
WHEN 16#76# TO 16#77# =>
--cycle cycles := 1;
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1; -- wait for data
temp1 := get_reg("00"&opcode(0)); -- the indirect dest addr
set_byte_dmem(temp1, pmem_s4_byte, indirect);
-- MOV DPTR, #data16
WHEN 16#90# =>
--cycle cycles := 2;
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
pc <= pc + 3;
dph <= pmem_s4_byte;
dpl <= pmem_s1_byte;
-- MOV bit addr, C
WHEN 16#92# =>
--cycle cycles := 2
WAIT UNTIL cycle_state = s2p1; -- wait for next cycle
pc <= pc + 2;
set_bit_dmem(pmem_s4_byte,cy);
-- MOV C, bit addr
WHEN 16#A2# =>
--cycle cycles := 1
pc <= pc + 2;
WAIT UNTIL cycle_state = s5p1;
cy <= get_bit_dmem(pmem_s4_byte);
-- MOVC A, @A + DPTR
WHEN 16#93# =>
--cycle cycles := 2;
temp1 := PC(15 DOWNTO 8);
temp2 := PC(7 DOWNTO 0);
-- Set the program counter, so that the addr will go out at s4p2,
-- and the new data come in at s1p1 of next cycle
pc(7 DOWNTO 0) <= acc + dpl;
IF conv_integer(acc)+conv_integer(dpl) > 255 THEN
pc(15 DOWNTO 8) <= dph + 1;
ELSE
pc(15 DOWNTO 8) <= dph;
END IF;
WAIT UNTIL cycle_state = s2p1;
acc <= pmem_s1_byte;
pc <= temp1 & temp2 + 1;
-- MOVC A, @A + PC
WHEN 16#83# =>
--cycle cycles := 2;
temp1 := PC(15 DOWNTO 8);
temp2 := PC(7 DOWNTO 0);
-- Set the program counter, so that the addr will go out at s4p2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -