📄 mc8051.vhd
字号:
IF rst = '1' THEN 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; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -