Line 1... |
Line 1... |
-- FPz8 mk1
|
-- FPz8 mk1 v0.99
|
-- Zilog Z8 Encore! 100% compatible softcore
|
-- Zilog Z8 Encore! 100% compatible softcore
|
-- Author: Fábio Pereira (fabio.jve@gmail.com)
|
-- Author: Fábio Pereira (fabio.jve@gmail.com)
|
|
-- Version: 0.99 Nov, 24th, 2016 (changed LDWX instruction, interrupts, condition code function, debugger command processor)
|
|
-- Version: 0.91 Nov, 15th, 2016
|
-- Version: 0.9 Nov, 11th, 2016
|
-- Version: 0.9 Nov, 11th, 2016
|
|
|
-- FPz8 is a softcore 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes
|
-- FPz8 is a softcore almost 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes
|
-- 2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority,
|
-- 2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority,
|
-- full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
|
-- full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
|
-- It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera
|
-- It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera
|
-- Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA
|
-- Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA
|
-- board used on the project).
|
-- board used on the project).
|
-- In a near future I plan to add some more features to the device (such as a timer and maybe other peripherals).
|
-- In a near future I plan to add some more features to the device (such as a timer and maybe other peripherals).
|
-- The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using those technologies). I also
|
-- The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using these technologies). I also
|
-- believe the FPz8 can be a very interesting tool for learning/teaching about VHDL, computing and microprocessors/microcontrollers
|
-- believe FPz8 can be a very interesting tool for learning/teaching VHDL, computing and microprocessors/microcontrollers
|
-- programming.
|
-- programming.
|
|
|
-- You are free to use and to modify FPz8 to fit your needs, except for comercial use (I don't expect anyone would do that anyway).
|
-- You are free to use and to modify FPz8 to fit your needs, except for comercial use (I don't expect anyone would do that anyway).
|
-- If you want to contribute to the project, contact me and share your thoughts.
|
-- If you want to contribute to the project, contact me and share your thoughts.
|
-- Don't forget to credit the author!
|
-- Don't forget to credit the author!
|
Line 28... |
Line 30... |
-- 0xFF8 - FCTL
|
-- 0xFF8 - FCTL
|
-- 0xFFC - FLAGS
|
-- 0xFFC - FLAGS
|
-- 0xFFD - RP
|
-- 0xFFD - RP
|
-- 0xFFE - SPH
|
-- 0xFFE - SPH
|
-- 0xFFF - SPL
|
-- 0xFFF - SPL
|
-- Also notice INT7 is not physically present as it is planned to be used with the coming timer peripheral
|
|
|
|
-- What else is missing from the original architecture?
|
-- What else is missing from the original architecture?
|
-- A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes
|
-- A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes,
|
|
-- no data memory related debug commands, no CRC debug command, no ID bytes
|
|
|
-- FPz8 was tested on a EP4CE6 mini board (50MHz clock)
|
-- FPz8 was tested on an EP4CE6 mini board (50MHz clock)
|
-- http://www.ebay.com/itm/EP4CE6-Mini-Board-USB-Blaster-Altera-Cyclone-IV-FPGA-CPLD-Nano-Size-
|
-- http://www.ebay.com/itm/EP4CE6-Mini-Board-USB-Blaster-Altera-Cyclone-IV-FPGA-CPLD-Nano-Size-
|
|
|
-- This work is licensed under the Creative Commons Attribution 4.0 International License.
|
-- This work is licensed under the Creative Commons Attribution 4.0 International License.
|
-- To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.
|
-- To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.
|
|
|
Line 49... |
Line 51... |
entity fpz8_cpu_v1 IS
|
entity fpz8_cpu_v1 IS
|
port
|
port
|
(
|
(
|
IAB : buffer std_logic_vector(15 downto 0); -- instruction address bus (16 bits)
|
IAB : buffer std_logic_vector(15 downto 0); -- instruction address bus (16 bits)
|
IDB : in std_logic_vector(7 downto 0); -- instruction data bus (8 bits)
|
IDB : in std_logic_vector(7 downto 0); -- instruction data bus (8 bits)
|
PWDB : out std_logic_vector(7 downto 0); -- program write data bus (8 bits)
|
IWDB : out std_logic_vector(7 downto 0); -- instruction write data bus (8 bits)
|
MAB : buffer std_logic_vector(11 downto 0); -- memory address bus (12 bits)
|
FRAB : buffer std_logic_vector(11 downto 0); -- file register address bus (12 bits)
|
MIDB : in std_logic_vector(7 downto 0); -- memory input data bus (8 bits)
|
FRIDB : in std_logic_vector(7 downto 0); -- memory input data bus (8 bits)
|
MODB : out std_logic_vector(7 downto 0); -- memory output data bus (8 bits)
|
FRODB : out std_logic_vector(7 downto 0); -- memory output data bus (8 bits)
|
RIDB : in std_logic_vector(7 downto 0); -- register input data bus (8 bits)
|
RIDB : in std_logic_vector(7 downto 0); -- register input data bus (8 bits)
|
RODB : out std_logic_vector(7 downto 0); -- register output data bus (8 bits)
|
RODB : out std_logic_vector(7 downto 0); -- register output data bus (8 bits)
|
PGM_WR : out std_logic; -- program memory write enable
|
PGM_WR : out std_logic; -- program memory write enable
|
WR : buffer std_logic; -- write enable
|
WR : buffer std_logic; -- write enable
|
REG_SEL : buffer std_logic; -- SFR select (addresses F00 to FFF, except internal registers)
|
REG_SEL : buffer std_logic; -- SFR select (addresses F00 to FFF, except internal registers)
|
Line 66... |
Line 68... |
INT2 : in std_logic; -- interrupt 2 input (vector 0x0012)
|
INT2 : in std_logic; -- interrupt 2 input (vector 0x0012)
|
INT3 : in std_logic; -- interrupt 3 input (vector 0x0010)
|
INT3 : in std_logic; -- interrupt 3 input (vector 0x0010)
|
INT4 : in std_logic; -- interrupt 4 input (vector 0x000E)
|
INT4 : in std_logic; -- interrupt 4 input (vector 0x000E)
|
INT5 : in std_logic; -- interrupt 5 input (vector 0x000C)
|
INT5 : in std_logic; -- interrupt 5 input (vector 0x000C)
|
INT6 : in std_logic; -- interrupt 6 input (vector 0x000A)
|
INT6 : in std_logic; -- interrupt 6 input (vector 0x000A)
|
|
INT7 : in std_logic; -- interrupt 7 input (vector 0x0008)
|
DBG_RX : in std_logic; -- debugger receive input
|
DBG_RX : in std_logic; -- debugger receive input
|
DBG_TX : buffer std_logic; -- debugger transmit output
|
DBG_TX : buffer std_logic; -- debugger transmit output
|
PAOUT : out std_logic_vector(7 downto 0); -- port A output data
|
PAOUT : out std_logic_vector(7 downto 0); -- port A output data
|
PAIN : in std_logic_vector(7 downto 0); -- port A input data
|
PAIN : in std_logic_vector(7 downto 0); -- port A input data
|
CLK : in std_logic; -- main clock
|
CLK : in std_logic; -- main clock
|
CLK_OUT : out std_logic; -- main gated-clock output
|
CLK_OUT : buffer std_logic; -- main clock output
|
CLK_OUTN : out std_logic; -- main inverted-gated-clock output
|
CLK_OUTN : out std_logic; -- main inverted clock output
|
STOP : buffer std_logic; -- stop output
|
STOP : buffer std_logic; -- stop output
|
|
RESET_OUT : out std_logic; -- reset output
|
RESET : in std_logic -- CPU reset
|
RESET : in std_logic -- CPU reset
|
);
|
);
|
end fpz8_cpu_v1;
|
end fpz8_cpu_v1;
|
|
|
architecture cpu of fpz8_cpu_v1 is
|
architecture cpu of fpz8_cpu_v1 is
|
Line 86... |
Line 90... |
type Tflags is record
|
type Tflags is record
|
C,Z,S,V,D,H,F2,F1 : std_logic;
|
C,Z,S,V,D,H,F2,F1 : std_logic;
|
end record;
|
end record;
|
shared variable CPU_FLAGS, ALU_FLAGS : Tflags;
|
shared variable CPU_FLAGS, ALU_FLAGS : Tflags;
|
shared variable ALU_NOUPDATE : std_logic;
|
shared variable ALU_NOUPDATE : std_logic;
|
shared variable INT7 : std_logic;
|
|
shared variable IRQE : std_logic;
|
shared variable IRQE : std_logic;
|
shared variable HALT : std_logic;
|
|
shared variable IRQ0 : std_logic_vector(7 downto 0); -- interrupts 0-7 flags
|
shared variable IRQ0 : std_logic_vector(7 downto 0); -- interrupts 0-7 flags
|
shared variable IRQ0ENH,IRQ0ENL : std_logic_vector(7 downto 0); -- interrupts 0-7 enable high and low
|
shared variable IRQ0ENH,IRQ0ENL : std_logic_vector(7 downto 0); -- interrupts 0-7 enable high and low
|
shared variable SP : std_logic_vector(11 downto 0); -- stack pointer
|
shared variable SP : std_logic_vector(11 downto 0); -- stack pointer
|
shared variable RP : std_logic_vector(7 downto 0); -- register pointer
|
shared variable RP : std_logic_vector(7 downto 0); -- register pointer
|
shared variable FCTL : std_logic_vector(7 downto 0); -- flash control
|
shared variable FCTL : std_logic_vector(7 downto 0); -- flash control
|
shared variable PAOUT_BUFFER : std_logic_vector(7 downto 0);
|
shared variable PAOUT_BUFFER : std_logic_vector(7 downto 0);
|
signal RXSYNC1, RXSYNC2 : std_logic;
|
signal RXSYNC1, RXSYNC2 : std_logic;
|
ATTRIBUTE preserve : boolean;
|
ATTRIBUTE preserve : boolean;
|
ATTRIBUTE preserve OF RXSYNC1 : signal IS true;
|
ATTRIBUTE preserve OF RXSYNC1 : signal IS true;
|
ATTRIBUTE preserve OF RXSYNC2 : signal IS true;
|
ATTRIBUTE preserve OF RXSYNC2 : signal IS true;
|
|
signal IRQ0_LATCH : std_logic_vector(7 downto 0); -- current state of IRQ inputs
|
|
attribute preserve of IRQ0_LATCH : signal is true;
|
|
|
constant ALU_ADD : std_logic_vector(3 downto 0):=x"0"; -- CZSVH D=0
|
constant ALU_ADD : std_logic_vector(3 downto 0):=x"0"; -- CZSVH D=0
|
constant ALU_ADC : std_logic_vector(3 downto 0):=x"1"; -- CZSVH D=0
|
constant ALU_ADC : std_logic_vector(3 downto 0):=x"1"; -- CZSVH D=0
|
constant ALU_SUB : std_logic_vector(3 downto 0):=x"2"; -- CZSVH D=1
|
constant ALU_SUB : std_logic_vector(3 downto 0):=x"2"; -- CZSVH D=1
|
constant ALU_SBC : std_logic_vector(3 downto 0):=x"3"; -- CZSVH D=1
|
constant ALU_SBC : std_logic_vector(3 downto 0):=x"3"; -- CZSVH D=1
|
Line 176... |
Line 180... |
elsif (ADDRESS=x"FC2") then IRQ0ENL := DATA; ------------------------------ IRQ0ENL register
|
elsif (ADDRESS=x"FC2") then IRQ0ENL := DATA; ------------------------------ IRQ0ENL register
|
elsif (ADDRESS=x"FCF") then IRQE := DATA(7); ------------------------------- IRQCTL register
|
elsif (ADDRESS=x"FCF") then IRQE := DATA(7); ------------------------------- IRQCTL register
|
elsif (ADDRESS=x"FD3") then ---------------------------------------------------- PAOUT register
|
elsif (ADDRESS=x"FD3") then ---------------------------------------------------- PAOUT register
|
PAOUT <= DATA;
|
PAOUT <= DATA;
|
PAOUT_BUFFER := DATA;
|
PAOUT_BUFFER := DATA;
|
else
|
else -- if it is not an internal SFR but ADDRESS>=0xF00 then it is an external register
|
REG_SEL <= '1';
|
REG_SEL <= '1'; -- enable external register select
|
RODB <= DATA;
|
RODB <= DATA; -- output data on register output data bus
|
end if;
|
end if;
|
else
|
else -- if ADDRESS < 0xF00 then it is a RAM register
|
MEM_SEL <= '1';
|
MEM_SEL <= '1'; -- enable external memory select
|
MODB <= DATA;
|
FRODB <= DATA; -- output data on file register output data bus
|
end if;
|
end if;
|
end datawrite;
|
end datawrite;
|
|
|
-- DATAREAD controls where the data to be read actually comes from (an internal register, an external register (through register data bus) or RAM)
|
-- DATAREAD controls where the data to be read actually comes from (an internal register, an external register (through register data bus) or RAM)
|
impure function DATAREAD
|
impure function DATAREAD
|
Line 211... |
Line 215... |
REG_SEL <= '1';
|
REG_SEL <= '1';
|
return RIDB;
|
return RIDB;
|
end if;
|
end if;
|
else
|
else
|
MEM_SEL <= '1';
|
MEM_SEL <= '1';
|
return MIDB;
|
return FRIDB;
|
end if;
|
end if;
|
end DATAREAD;
|
end DATAREAD;
|
|
|
-- CONDITIONCODE returns the result of a logical condition (for conditional jumps)
|
-- CONDITIONCODE returns the result of a logical condition (for conditional jumps)
|
function CONDITIONCODE
|
function CONDITIONCODE
|
Line 223... |
Line 227... |
begin
|
begin
|
case CONDITION is
|
case CONDITION is
|
when x"0" =>
|
when x"0" =>
|
return '0';
|
return '0';
|
when x"1" =>
|
when x"1" =>
|
return ALU_FLAGS.S xor ALU_FLAGS.V;
|
return CPU_FLAGS.S xor CPU_FLAGS.V;
|
when x"2" =>
|
when x"2" =>
|
return ALU_FLAGS.Z or (ALU_FLAGS.S xor ALU_FLAGS.V);
|
return CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V);
|
when x"3" =>
|
when x"3" =>
|
return ALU_FLAGS.C or ALU_FLAGS.Z;
|
return CPU_FLAGS.C or CPU_FLAGS.Z;
|
when x"4" =>
|
when x"4" =>
|
return ALU_FLAGS.V;
|
return CPU_FLAGS.V;
|
when x"5" =>
|
when x"5" =>
|
return ALU_FLAGS.S;
|
return CPU_FLAGS.S;
|
when x"6" =>
|
when x"6" =>
|
return ALU_FLAGS.Z;
|
return CPU_FLAGS.Z;
|
when x"7" =>
|
when x"7" =>
|
return ALU_FLAGS.C;
|
return CPU_FLAGS.C;
|
when x"8" =>
|
when x"8" =>
|
return '1';
|
return '1';
|
when x"9" =>
|
when x"9" =>
|
return NOT (ALU_FLAGS.S xor ALU_FLAGS.V);
|
return NOT (CPU_FLAGS.S xor CPU_FLAGS.V);
|
when x"A" =>
|
when x"A" =>
|
return NOT (ALU_FLAGS.Z or (ALU_FLAGS.S xor ALU_FLAGS.V));
|
return NOT (CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V));
|
when x"B" =>
|
when x"B" =>
|
return (NOT ALU_FLAGS.C) AND (NOT ALU_FLAGS.Z);
|
return (NOT CPU_FLAGS.C) AND (NOT CPU_FLAGS.Z);
|
when x"C" =>
|
when x"C" =>
|
return NOT ALU_FLAGS.V;
|
return NOT CPU_FLAGS.V;
|
when x"D" =>
|
when x"D" =>
|
return NOT ALU_FLAGS.S;
|
return NOT CPU_FLAGS.S;
|
when x"E" =>
|
when x"E" =>
|
return NOT ALU_FLAGS.Z;
|
return NOT CPU_FLAGS.Z;
|
when others =>
|
when others =>
|
return NOT ALU_FLAGS.C;
|
return NOT CPU_FLAGS.C;
|
end case;
|
end case;
|
end CONDITIONCODE;
|
end CONDITIONCODE;
|
|
|
-- ADDRESSER12 generates a 12-bit address (it decides when to use escaped addressing mode)
|
-- ADDRESSER12 generates a 12-bit address (it decides when to use escaped addressing mode)
|
function ADDRESSER12
|
function ADDRESSER12
|
Line 277... |
Line 281... |
return RP(3 downto 0) & RP(7 downto 4) & ADDR(3 downto 0);
|
return RP(3 downto 0) & RP(7 downto 4) & ADDR(3 downto 0);
|
else return RP(3 downto 0) & ADDR(7 downto 0); -- full address
|
else return RP(3 downto 0) & ADDR(7 downto 0); -- full address
|
end if;
|
end if;
|
end ADDRESSER8;
|
end ADDRESSER8;
|
|
|
-- ADDRESSER12 generates a 12-bit address from a 4-bit address (using RP register)
|
-- ADDRESSER4 generates a 12-bit address from a 4-bit address (using RP register)
|
function ADDRESSER4
|
function ADDRESSER4
|
( ADDR : in std_logic_vector(3 downto 0)) return std_logic_vector is
|
( ADDR : in std_logic_vector(3 downto 0)) return std_logic_vector is
|
begin
|
begin
|
return RP(3 downto 0) & RP(7 downto 4) & ADDR;
|
return RP(3 downto 0) & RP(7 downto 4) & ADDR;
|
end ADDRESSER4;
|
end ADDRESSER4;
|
Line 462... |
Line 466... |
else return ADDR16 + (x"FF" & OFFSET);
|
else return ADDR16 + (x"FF" & OFFSET);
|
end if;
|
end if;
|
end ADDER16;
|
end ADDER16;
|
|
|
begin
|
begin
|
clock_out: process(CLK)
|
clock_out: process(CLK,RESET)
|
|
variable CKDIVIDER : integer range 0 to 2;
|
begin
|
begin
|
CLK_OUTN <= not CLK;
|
if (RESET='1') then
|
CLK_OUT <= CLK;
|
CKDIVIDER := 0;
|
end process;
|
CLK_OUTN <= '1';
|
|
CLK_OUT <= '0';
|
|
elsif (rising_edge(CLK)) then
|
|
CLK_OUTN <= '1';
|
|
CLK_OUT <= '0';
|
|
CKDIVIDER := CKDIVIDER + 1;
|
|
if (CKDIVIDER=0) then -- main clock (50MHz) is divided by 3, resulting in a 16.66MHz system clock
|
|
CLK_OUT <= '1';
|
|
CLK_OUTN <= '0';
|
|
end if;
|
|
end if;
|
|
end process; -- clock_out process
|
-- main process controls debugging and instruction fetching and decoding along
|
-- main process controls debugging and instruction fetching and decoding along
|
main: process (CLK,RESET,DBG_RX)
|
main: process (CLK_OUT,RESET,DBG_RX)
|
-- CPU state machine
|
-- CPU state machine
|
type Tcpu_state is (
|
type Tcpu_state is (
|
CPU_DECOD,
|
CPU_DECOD,
|
CPU_INDRR,
|
CPU_INDRR, -- indirect rr mode
|
CPU_MUL, CPU_MUL1, CPU_MUL2,
|
CPU_MUL, CPU_MUL1, CPU_MUL2, -- MUL instruction
|
CPU_XADTOM,
|
CPU_XADTOM, -- address with offset to memory
|
CPU_MTOXAD, CPU_MTOXAD2,
|
CPU_MTOXAD, CPU_MTOXAD2, -- memory to address with offset
|
CPU_XRTOM,
|
CPU_XRTOM, -- register with offset to memory
|
CPU_XRRTORR, CPU_XRRTORR2,
|
CPU_XRRTORR, CPU_XRRTORR2, -- register pair with offset to register pair
|
CPU_XRRTORR3, CPU_XRRTORR4,
|
CPU_XRRTORR3, CPU_XRRTORR4,
|
CPU_IMTOIRR, CPU_MTOIRR, -- indirect and direct to indirect register pair addressing mode
|
CPU_IMTOIRR, CPU_MTOIRR, -- indirect and direct to indirect register pair addressing mode
|
CPU_IRRS, CPU_IRRS2,
|
CPU_IRRS, CPU_IRRS2, -- indirect register pair as source
|
CPU_XRRD, CPU_XRRD2, CPU_XRRD3, -- indexed rr pair as destination
|
CPU_XRRD, CPU_XRRD2, CPU_XRRD3, -- indexed rr pair as destination
|
CPU_XRRS, CPU_XRRS2, CPU_XRRS3, -- indexed rr pair as source
|
CPU_XRRS, CPU_XRRS2, CPU_XRRS3, -- indexed rr pair as source
|
CPU_IND1, CPU_IND2, -- indirect memory access
|
CPU_IND1, CPU_IND2, -- indirect memory access
|
CPU_ISMD1, -- indirect source to memory destination
|
CPU_ISMD1, -- indirect source to memory destination
|
CPU_TMA, -- Two memory access instructions (register to/with register)
|
CPU_TMA, -- Two memory access instructions (register to/with register)
|
CPU_OMA, -- One memory access instructions (immediate to/with register)
|
CPU_OMA, -- One memory access instructions (immediate to/with register)
|
CPU_OMA2, -- One memory access instructions (immediate to/with register) logic unit related
|
CPU_OMA2, -- One memory access instructions (immediate to/with register) logic unit related
|
CPU_DMAB, -- Decrement address bus (for word access)
|
CPU_DMAB, -- Decrement address bus (for word access)
|
CPU_LDW, CPU_LDW2,
|
CPU_LDW, CPU_LDW2, CPU_LDW3, -- load word instruction
|
CPU_LDPTOIM, CPU_LDPTOIM2,
|
CPU_LDW4, CPU_LDW5,
|
CPU_LDPTOM, CPU_LDPTOM2,
|
CPU_LDPTOIM, CPU_LDPTOIM2, -- load program to indirect memory
|
|
CPU_LDPTOM, CPU_LDPTOM2, -- load program to memory
|
CPU_LDPTOM3, CPU_LDPTOM4,
|
CPU_LDPTOM3, CPU_LDPTOM4,
|
CPU_LDMTOP, CPU_LDMTOP2,
|
CPU_LDMTOP, CPU_LDMTOP2, -- load memory to program
|
CPU_BIT,
|
CPU_BIT, -- BIT instruction
|
CPU_IBTJ, CPU_BTJ,
|
CPU_IBTJ, CPU_BTJ, -- BTJ instruction
|
CPU_DJNZ,
|
CPU_DJNZ, -- DJNZ instruction
|
CPU_INDJUMP, CPU_INDJUMP2,
|
CPU_INDJUMP, CPU_INDJUMP2, -- indirect JP
|
CPU_TRAP, CPU_TRAP2,
|
CPU_TRAP, CPU_TRAP2, -- TRAP instruction
|
CPU_INDSTACK, CPU_INDSTACK2,
|
CPU_INDSTACK, CPU_INDSTACK2, -- indirect stacking
|
CPU_STACK, CPU_STACK1,
|
CPU_STACK, CPU_STACK1, -- stacking operations
|
CPU_STACK2, CPU_STACK3,
|
CPU_STACK2, CPU_STACK3,
|
CPU_UNSTACK, CPU_UNSTACK2,
|
CPU_UNSTACK, CPU_UNSTACK2, -- unstacking operations
|
CPU_UNSTACK3,
|
CPU_UNSTACK3,
|
CPU_STORE, -- store results, no change to the flags
|
CPU_STORE, -- store results, no change to the flags
|
CPU_VECTOR, CPU_VECTOR2,
|
CPU_VECTOR, CPU_VECTOR2, -- vectoring stages
|
CPU_HALTED,
|
CPU_RESET, -- reset state
|
CPU_RESET,
|
CPU_ILLEGAL -- illegal state
|
CPU_ILLEGAL
|
|
);
|
);
|
type Tfetch_state is (
|
type Tfetch_state is (
|
F_ADDR, -- instruction queue is initializing, reset pointers and empty queue
|
F_ADDR, -- instruction queue is initializing, reset pointers and empty queue
|
F_READ -- instruction queue is fetching opcodes
|
F_READ -- instruction queue is fetching opcodes
|
);
|
);
|
Line 576... |
Line 592... |
variable CPU_STATE : TCPU_STATE; -- current CPU state
|
variable CPU_STATE : TCPU_STATE; -- current CPU state
|
variable DBG_UART : Tdbg_uart;
|
variable DBG_UART : Tdbg_uart;
|
variable DBG_CMD : Tdbg_command;
|
variable DBG_CMD : Tdbg_command;
|
variable CAN_FETCH : std_logic; -- controls whether the instruction queue can actually fetch opcodes
|
variable CAN_FETCH : std_logic; -- controls whether the instruction queue can actually fetch opcodes
|
variable LU_INSTRUCTION : std_logic; -- indicates a LU2-related instruction
|
variable LU_INSTRUCTION : std_logic; -- indicates a LU2-related instruction
|
|
variable INT_FLAG : std_logic; -- indicates an interrupt
|
variable WORD_DATA : std_logic; -- indicates a 16-bit data instruction
|
variable WORD_DATA : std_logic; -- indicates a 16-bit data instruction
|
|
variable HALT : std_logic; -- indicates the CPU is halted
|
variable PC : std_logic_vector(15 downto 0); -- program counter
|
variable PC : std_logic_vector(15 downto 0); -- program counter
|
variable FETCH_ADDR : std_logic_vector(15 downto 0); -- next address to be fetched
|
variable FETCH_ADDR : std_logic_vector(15 downto 0); -- next address to be fetched
|
variable DEST_ADDR16 : std_logic_vector(15 downto 0); -- temporary 16-bit destination address
|
variable DEST_ADDR16 : std_logic_vector(15 downto 0); -- temporary 16-bit destination address
|
variable DEST_ADDR : std_logic_vector(11 downto 0); -- temporary 12-bit destination address
|
variable DEST_ADDR : std_logic_vector(11 downto 0); -- temporary 12-bit destination address
|
variable TEMP_DATA : std_logic_vector(7 downto 0); -- temporary 8-bit data
|
variable TEMP_DATA : std_logic_vector(7 downto 0); -- temporary 8-bit data
|
variable OLD_IRQ0 : std_logic_vector(7 downto 0); -- previous state of IRQs
|
variable OLD_IRQ0 : std_logic_vector(7 downto 0); -- previous state of IRQ inputs
|
variable INTVECT : std_logic_vector(7 downto 0); -- current interrupt vector (lower 8-bits)
|
variable INTVECT : std_logic_vector(7 downto 0); -- current interrupt vector (lower 8-bits)
|
variable RESULT : std_logic_vector(7 downto 0); -- temporary 8-bit result
|
variable RESULT : std_logic_vector(7 downto 0); -- temporary 8-bit result
|
variable TEMP_OP : std_logic_vector(3 downto 0); -- ALU/LU2 operation code
|
variable TEMP_OP : std_logic_vector(3 downto 0); -- ALU/LU2 operation code
|
variable ATM_COUNTER : integer range 0 to 3; -- temporary interrupt disable counter (ATM instruction)
|
variable ATM_COUNTER : integer range 0 to 3; -- temporary interrupt disable counter (ATM instruction)
|
variable NUM_BYTES : integer range 0 to 5; -- number of bytes decoded
|
variable NUM_BYTES : integer range 0 to 5; -- number of bytes decoded
|
variable CKDIVIDER : integer range 0 to 2;
|
|
type Tinstructionqueue is record
|
type Tinstructionqueue is record
|
WRPOS : integer range 0 to 7; -- instruction queue write pointer
|
WRPOS : integer range 0 to 7; -- instruction queue write pointer
|
RDPOS : integer range 0 to 7; -- instruction queue read pointer
|
RDPOS : integer range 0 to 7; -- instruction queue read pointer
|
CNT : integer range 0 to 7; -- instruction queue available bytes
|
CNT : integer range 0 to 7; -- instruction queue available bytes
|
FETCH_STATE : tfetch_state;
|
FETCH_STATE : tfetch_state;
|
Line 612... |
Line 629... |
SINGLESTEP : std_logic;
|
SINGLESTEP : std_logic;
|
end record;
|
end record;
|
variable OCD : Tocdflags;
|
variable OCD : Tocdflags;
|
|
|
begin
|
begin
|
if (reset='1') then -- reset operations
|
RESET_OUT <= RESET or OCDCR.RST;
|
|
if (RESET='1') then -- reset operations
|
IAB <= x"0002";
|
IAB <= x"0002";
|
MAB <= x"000";
|
FRAB <= x"000";
|
PWDB <= x"00";
|
IWDB <= x"00";
|
SP := x"000";
|
SP := x"000";
|
RP := x"00";
|
RP := x"00";
|
WR <= '0';
|
WR <= '0';
|
PGM_WR <= '0';
|
PGM_WR <= '0';
|
STOP <= '0';
|
STOP <= '0';
|
Line 641... |
Line 659... |
IRQ0 := x"00";
|
IRQ0 := x"00";
|
OLD_IRQ0 := x"00";
|
OLD_IRQ0 := x"00";
|
IRQ0ENH := x"00";
|
IRQ0ENH := x"00";
|
IRQ0ENL := x"00";
|
IRQ0ENL := x"00";
|
ATM_COUNTER := 0;
|
ATM_COUNTER := 0;
|
CKDIVIDER := 0;
|
|
CPU_STATE := CPU_VECTOR;
|
CPU_STATE := CPU_VECTOR;
|
elsif (rising_edge(clk)) then
|
elsif (rising_edge(CLK_OUT)) then
|
if (OLD_IRQ0(0)='0' and INT0='1') then IRQ0(0) := '1'; end if;
|
IRQ0_LATCH <= INT7&INT6&INT5&INT4&INT3&INT2&INT1&INT0;
|
if (OLD_IRQ0(1)='0' and INT1='1') then IRQ0(1) := '1'; end if;
|
if (OLD_IRQ0(0)/=IRQ0_LATCH(0)) then IRQ0(0) := '1'; end if;
|
if (OLD_IRQ0(2)='0' and INT2='1') then IRQ0(2) := '1'; end if;
|
if (OLD_IRQ0(1)/=IRQ0_LATCH(1)) then IRQ0(1) := '1'; end if;
|
if (OLD_IRQ0(3)='0' and INT3='1') then IRQ0(3) := '1'; end if;
|
if (OLD_IRQ0(2)/=IRQ0_LATCH(2)) then IRQ0(2) := '1'; end if;
|
if (OLD_IRQ0(4)='0' and INT4='1') then IRQ0(4) := '1'; end if;
|
if (OLD_IRQ0(3)/=IRQ0_LATCH(3)) then IRQ0(3) := '1'; end if;
|
if (OLD_IRQ0(5)='0' and INT5='1') then IRQ0(5) := '1'; end if;
|
if (OLD_IRQ0(4)/=IRQ0_LATCH(4)) then IRQ0(4) := '1'; end if;
|
if (OLD_IRQ0(6)='0' and INT6='1') then IRQ0(6) := '1'; end if;
|
if (OLD_IRQ0(5)/=IRQ0_LATCH(5)) then IRQ0(5) := '1'; end if;
|
OLD_IRQ0 := INT7&INT6&INT5&INT4&INT3&INT2&INT1&INT0;
|
if (OLD_IRQ0(6)/=IRQ0_LATCH(6)) then IRQ0(6) := '1'; end if;
|
CKDIVIDER := CKDIVIDER + 1;
|
if (OLD_IRQ0(7)/=IRQ0_LATCH(7)) then IRQ0(7) := '1'; end if;
|
if (CKDIVIDER=0) then -- main clock (50MHz) is divided by 3, resulting in a 16.66MHz system clock
|
OLD_IRQ0 := IRQ0_LATCH;
|
|
|
WR <= '0';
|
WR <= '0';
|
PGM_WR <= '0';
|
PGM_WR <= '0';
|
|
|
-- This is the instruction queue FSM
|
-- start of instruction queue FSM
|
if (CAN_FETCH='1') then
|
if (CAN_FETCH='1') then
|
if (IQUEUE.FETCH_STATE=F_ADDR) then
|
if (IQUEUE.FETCH_STATE=F_ADDR) then
|
FETCH_ADDR := PC;
|
FETCH_ADDR := PC;
|
IAB <= PC;
|
IAB <= PC;
|
IQUEUE.WRPOS := 0;
|
IQUEUE.WRPOS := 0;
|
Line 678... |
Line 696... |
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
if (IQUEUE.CNT=7) then IQUEUE.FULL:='1'; else IQUEUE.FULL:='0';
|
if (IQUEUE.CNT=7) then IQUEUE.FULL:='1'; else IQUEUE.FULL:='0';
|
end if;
|
end if;
|
-- This is the end of instruction queue FSM
|
-- end of instruction queue FSM
|
|
|
-- These are the Debugger FSMs
|
-- start of debugger UART
|
DBG_UART.BAUDPRE := DBG_UART.BAUDPRE+1;
|
DBG_UART.BAUDPRE := DBG_UART.BAUDPRE+1; -- baudrate prescaler
|
if (DBG_UART.BAUDPRE=0) then
|
if (DBG_UART.BAUDPRE=0) then
|
DBG_UART.BAUDCNTRX := DBG_UART.BAUDCNTRX+1;
|
DBG_UART.BAUDCNTRX := DBG_UART.BAUDCNTRX+1;
|
DBG_UART.BAUDCNTTX := DBG_UART.BAUDCNTTX+1;
|
DBG_UART.BAUDCNTTX := DBG_UART.BAUDCNTTX+1;
|
end if;
|
end if;
|
RXSYNC2 <= DBG_RX;
|
RXSYNC2 <= DBG_RX; -- DBG_RX input synchronization
|
RXSYNC1 <= RXSYNC2;
|
RXSYNC1 <= RXSYNC2; -- RXSYNC1 is a synchronized DBG_RX signal
|
case DBG_UART.RX_STATE is
|
case DBG_UART.RX_STATE is
|
when DBGST_NOSYNC =>
|
when DBGST_NOSYNC =>
|
DBG_UART.DBG_SYNC := '0';
|
DBG_UART.DBG_SYNC := '0';
|
DBG_UART.RX_DONE := '0';
|
DBG_UART.RX_DONE := '0';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
Line 787... |
Line 805... |
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
if (DBG_UART.BAUDCNTTX=x"FFF") then
|
if (DBG_UART.BAUDCNTTX=x"FFF") then
|
DBG_UART.TX_STATE:=DBGTX_INIT;
|
DBG_UART.TX_STATE:=DBGTX_INIT;
|
end if;
|
end if;
|
end case;
|
end case;
|
if (RXSYNC1='0') then DBG_TX <='0';
|
if (RXSYNC1='0') then DBG_TX <='0'; -- this mimics open-collector feature of OCD communication
|
end if;
|
end if;
|
|
-- end of the debugger UART
|
|
|
|
-- This is the instruction decoder
|
|
case CPU_STATE IS
|
|
when CPU_DECOD =>
|
|
TEMP_OP := ALU_LD; -- default ALU operation is load
|
|
LU_INSTRUCTION := '0'; -- default is ALU operation (instead of LU2)
|
|
INT_FLAG := '0'; -- reset temporary interrupt flag
|
|
WORD_DATA := '0'; -- default is 8-bit operation
|
|
INTVECT := x"00"; -- default vector is 0x00
|
|
NUM_BYTES := 0; -- default instruction length is 0 bytes
|
|
|
|
-- start of debugger command processor
|
case DBG_CMD is
|
case DBG_CMD is
|
when DBG_WAIT_CMD =>
|
when DBG_WAIT_CMD =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
case DBG_UART.RX_DATA is
|
case DBG_UART.RX_DATA is
|
when DBGCMD_READ_REV => DBG_CMD := DBG_SEND_REV;
|
when DBGCMD_READ_REV => DBG_CMD := DBG_SEND_REV;
|
Line 810... |
Line 841... |
when DBGCMD_EXEC => DBG_CMD := DBG_EXEC;
|
when DBGCMD_EXEC => DBG_CMD := DBG_EXEC;
|
when others =>
|
when others =>
|
end case;
|
end case;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
end if;
|
end if;
|
when DBG_SEND_REV =>
|
when DBG_SEND_REV => -- read revision first byte
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=x"01";
|
DBG_UART.TX_DATA:=x"01";
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_SEND_REV2;
|
DBG_CMD := DBG_SEND_REV2;
|
end if;
|
end if;
|
when DBG_SEND_REV2 =>
|
when DBG_SEND_REV2 => -- read revision second byte
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=x"00";
|
DBG_UART.TX_DATA:=x"00";
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_SEND_STATUS =>
|
when DBG_SEND_STATUS => -- read OCD status
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=OCDCR.DBGMODE&HALT&"000000";
|
DBG_UART.TX_DATA:=OCDCR.DBGMODE&HALT&"000000";
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_WRITE_CTRL =>
|
when DBG_WRITE_CTRL => -- write OCD control register
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
OCDCR.DBGMODE := DBG_UART.RX_DATA(7);
|
OCDCR.DBGMODE := DBG_UART.RX_DATA(7);
|
OCDCR.BRKEN := DBG_UART.RX_DATA(6);
|
OCDCR.BRKEN := DBG_UART.RX_DATA(6);
|
OCDCR.DBGACK := DBG_UART.RX_DATA(5);
|
OCDCR.DBGACK := DBG_UART.RX_DATA(5);
|
Line 840... |
Line 871... |
OCDCR.RST := DBG_UART.RX_DATA(0);
|
OCDCR.RST := DBG_UART.RX_DATA(0);
|
if (OCDCR.RST='1') then CPU_STATE:=CPU_RESET;
|
if (OCDCR.RST='1') then CPU_STATE:=CPU_RESET;
|
end if;
|
end if;
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_SEND_CTRL =>
|
when DBG_SEND_CTRL => -- read OCD control register
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=OCDCR.DBGMODE&OCDCR.BRKEN&OCDCR.DBGACK&OCDCR.BRKLOOP&"000"&OCDCR.RST;
|
DBG_UART.TX_DATA:=OCDCR.DBGMODE&OCDCR.BRKEN&OCDCR.DBGACK&OCDCR.BRKLOOP&"000"&OCDCR.RST;
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_WRITE_PC =>
|
when DBG_WRITE_PC => -- write PC high byte
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
PC(15 downto 8) := DBG_UART.RX_DATA;
|
PC(15 downto 8) := DBG_UART.RX_DATA;
|
DBG_CMD := DBG_WRITE_PC2;
|
DBG_CMD := DBG_WRITE_PC2;
|
end if;
|
end if;
|
when DBG_WRITE_PC2 =>
|
when DBG_WRITE_PC2 => -- write PC low byte
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
PC(7 downto 0) := DBG_UART.RX_DATA;
|
PC(7 downto 0) := DBG_UART.RX_DATA;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.CNT := 0;
|
IQUEUE.CNT := 0;
|
CAN_FETCH := '1';
|
CAN_FETCH := '1';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_SEND_PC =>
|
when DBG_SEND_PC => -- read PC high byte
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=PC(15 downto 8);
|
DBG_UART.TX_DATA:=PC(15 downto 8);
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_SEND_PC2;
|
DBG_CMD := DBG_SEND_PC2;
|
end if;
|
end if;
|
when DBG_SEND_PC2 =>
|
when DBG_SEND_PC2 => -- read PC high byte
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=PC(7 downto 0);
|
DBG_UART.TX_DATA:=PC(7 downto 0);
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
end if;
|
end if;
|
when DBG_WRITE_REG =>
|
when DBG_WRITE_REG => -- write to SFR/user registers
|
DBG_UART.WRT := '1';
|
DBG_UART.WRT := '1';
|
DBG_CMD := DBG_REG;
|
DBG_CMD := DBG_REG;
|
when DBG_READ_REG =>
|
when DBG_READ_REG => -- read SFR/user registers
|
DBG_UART.WRT := '0';
|
DBG_UART.WRT := '0';
|
DBG_CMD := DBG_REG;
|
DBG_CMD := DBG_REG;
|
when DBG_REG =>
|
when DBG_REG => -- proceed with register read/write
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
CAN_FETCH := '0';
|
FRAB(11 downto 8) <= DBG_UART.RX_DATA(3 downto 0);
|
MAB(11 downto 8) <= DBG_UART.RX_DATA(3 downto 0);
|
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_REG2;
|
DBG_CMD := DBG_REG2;
|
end if;
|
end if;
|
when DBG_REG2 =>
|
when DBG_REG2 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
MAB(7 downto 0) <= DBG_UART.RX_DATA;
|
FRAB(7 downto 0) <= DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_REG3;
|
DBG_CMD := DBG_REG3;
|
end if;
|
end if;
|
when DBG_REG3 =>
|
when DBG_REG3 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
DBG_UART.SIZE := x"00"&DBG_UART.RX_DATA;
|
DBG_UART.SIZE := x"00"&DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_REG4;
|
DBG_CMD := DBG_REG4;
|
end if;
|
end if;
|
when DBG_REG4 =>
|
when DBG_REG4 =>
|
if (OCDCR.DBGMODE='1') then
|
|
if (DBG_UART.WRT='1') then
|
if (DBG_UART.WRT='1') then
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
TEMP_DATA := DBG_UART.RX_DATA;
|
TEMP_DATA := DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_REG5;
|
DBG_CMD := DBG_REG5;
|
end if;
|
end if;
|
else
|
else
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=DATAREAD(MAB);
|
DBG_UART.TX_DATA:=DATAREAD(FRAB);
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_REG5;
|
DBG_CMD := DBG_REG5;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
when DBG_REG5 =>
|
when DBG_REG5 =>
|
if (CPU_STATE=CPU_DECOD) then
|
FRAB <= FRAB + 1;
|
MAB <= MAB + 1;
|
|
DBG_UART.SIZE := DBG_UART.SIZE - 1;
|
DBG_UART.SIZE := DBG_UART.SIZE - 1;
|
if (DBG_UART.SIZE=x"0000") then
|
if (DBG_UART.SIZE=x"0000") then
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
CAN_FETCH := '1';
|
|
else DBG_CMD := DBG_REG4;
|
else DBG_CMD := DBG_REG4;
|
end if;
|
end if;
|
end if;
|
|
when DBG_WRITE_PROGMEM =>
|
when DBG_WRITE_PROGMEM =>
|
DBG_UART.WRT := '1';
|
DBG_UART.WRT := '1';
|
DBG_CMD := DBG_PROGMEM;
|
DBG_CMD := DBG_PROGMEM;
|
when DBG_READ_PROGMEM =>
|
when DBG_READ_PROGMEM =>
|
DBG_UART.WRT := '0';
|
DBG_UART.WRT := '0';
|
Line 960... |
Line 985... |
DBG_CMD := DBG_PROGMEM5;
|
DBG_CMD := DBG_PROGMEM5;
|
end if;
|
end if;
|
when DBG_PROGMEM5 =>
|
when DBG_PROGMEM5 =>
|
if (DBG_UART.WRT='1') then
|
if (DBG_UART.WRT='1') then
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
PWDB <= DBG_UART.RX_DATA;
|
IWDB <= DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
PGM_WR <= '1';
|
PGM_WR <= '1';
|
DBG_CMD := DBG_PROGMEM6;
|
DBG_CMD := DBG_PROGMEM6;
|
end if;
|
end if;
|
else
|
else
|
Line 1014... |
Line 1039... |
end if;
|
end if;
|
end if;
|
end if;
|
when DBG_EXEC3 =>
|
when DBG_EXEC3 =>
|
if (OCD.SINGLESTEP='1') then DBG_CMD := DBG_EXEC2; else
|
if (OCD.SINGLESTEP='1') then DBG_CMD := DBG_EXEC2; else
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
CAN_FETCH:='0';
|
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
end if;
|
end if;
|
when others =>
|
when others =>
|
end case;
|
end case;
|
-- This is the end of the debugger code
|
-- end of debugger command processor
|
|
|
-- This is the main instruction decoder
|
|
case CPU_STATE IS
|
|
when CPU_DECOD =>
|
|
TEMP_OP := ALU_LD; -- default ALU operation is load
|
|
LU_INSTRUCTION := '0'; -- default is ALU operation (instead of LU2)
|
|
WORD_DATA := '0'; -- default is 8-bit operation
|
|
INTVECT := x"00"; -- default vector is 0x00
|
|
NUM_BYTES := 0; -- default instruction length is 0 bytes
|
|
if (ATM_COUNTER/=3) then ATM_COUNTER := ATM_COUNTER+1;
|
if (ATM_COUNTER/=3) then ATM_COUNTER := ATM_COUNTER+1;
|
else -- interrupt processing *****************************************************************************
|
else -- interrupt processing *****************************************************************************
|
if (IRQE='1') then -- if interrupts are enabled
|
if (IRQE='1') then -- if interrupts are enabled
|
-- first the highest priority interrupts
|
-- first the highest priority level interrupts
|
if ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='1') then
|
if ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='1') then
|
INTVECT:=x"08";
|
INTVECT:=x"08";
|
IRQ0(7):='0';
|
IRQ0(7):='0';
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='1') then
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='1') then
|
INTVECT:=x"0A";
|
INTVECT:=x"0A";
|
Line 1109... |
Line 1125... |
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='0') and IRQ0ENL(0)='1') then
|
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='0') and IRQ0ENL(0)='1') then
|
INTVECT:=x"16";
|
INTVECT:=x"16";
|
IRQ0(0):='0';
|
IRQ0(0):='0';
|
end if;
|
end if;
|
if (INTVECT/=x"00") then
|
if (INTVECT/=x"00") then
|
|
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
|
DEST_ADDR16 := PC;
|
DEST_ADDR16 := PC;
|
IAB <= x"00"&INTVECT; -- build the address of the interrupt vector
|
IAB <= x"00"&INTVECT; -- build the interrupt vector address
|
SP := SP - 1; -- prepare stack pointer by decrementing it
|
SP := SP - 1; -- prepare stack pointer by decrementing it
|
MAB <= SP; -- put SP on MAB
|
FRAB <= SP; -- put SP on FRAB
|
CAN_FETCH := '0'; -- disable instruction fetching
|
CAN_FETCH := '0'; -- disable instruction fetching
|
IQUEUE.CNT := 0; -- empty instruction queue
|
OCD.SINGLESTEP := '0'; -- disable stepping
|
|
IQUEUE.CNT := 0; -- set queue empty
|
STOP <= '0'; -- disable stop bit
|
STOP <= '0'; -- disable stop bit
|
LU_INSTRUCTION := '1'; -- the stacking uses this bit to flag it is an interrupt stacking operation
|
HALT := '0'; -- disable halt mode
|
CPU_STATE := CPU_STACK;
|
INT_FLAG := '1'; -- signal it is an interrupt stacking operation
|
end if;
|
CPU_STATE := CPU_VECTOR;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end if; -- if IRQE=1
|
|
end if; -- if ATM_COUNTER...
|
|
if (STOP='0' and HALT='0') then
|
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
|
if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 5-byte instructions --
|
-- 5-byte instructions --
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
if (IQUEUE.CNT>=5) then
|
if (IQUEUE.CNT>=5) then -- 5-byte instructions
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
---------------------------------------------------------------------------------------------- CPC ER2,ER1 instruction
|
---------------------------------------------------------------------------------------------- CPC ER2,ER1 instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A8") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A8") then
|
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
|
TEMP_OP := ALU_CPC;
|
TEMP_OP := ALU_CPC;
|
NUM_BYTES := 5;
|
NUM_BYTES := 5;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
---------------------------------------------------------------------------------------------- CPC IMM,ER1 instruction
|
---------------------------------------------------------------------------------------------- CPC IMM,ER1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A9") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A9") then
|
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_OP := ALU_CPC;
|
TEMP_OP := ALU_CPC;
|
NUM_BYTES := 5;
|
NUM_BYTES := 5;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
--------------------------------------------------------------------------------------------- LDWX ER1,ER2 instruction
|
--------------------------------------------------------------------------------------------- LDWX ER1,ER2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"E8") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"E8") then
|
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
|
NUM_BYTES := 5;
|
NUM_BYTES := 5;
|
CPU_STATE := CPU_LDW;
|
CPU_STATE := CPU_LDW;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 1160... |
Line 1180... |
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 4-byte instructions --
|
-- 4-byte instructions --
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
if (IQUEUE.CNT>=4) then
|
if (IQUEUE.CNT>=4) then -- 4-byte instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then ------------------------------------------------ column 9 instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then ------------------------------------------------ column 9 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => ------------------------------------------------------------------------- LDX rr1,r2,X instruction
|
when x"8" => ------------------------------------------------------------------------- LDX rr1,r2,X instruction
|
when x"9" => ------------------------------------------------------------------------ LEA rr1,rr2,X instruction
|
when x"9" => ------------------------------------------------------------------------ LEA rr1,rr2,X instruction
|
when x"C" =>
|
when x"C" =>
|
Line 1172... |
Line 1192... |
when x"D" =>
|
when x"D" =>
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
when x"F" =>
|
when x"F" =>
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
when others => -------------------------------------------------------------- IM,ER1 addressing mode instructions
|
when others => -------------------------------------------------------------- IM,ER1 addressing mode instructions
|
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
end case;
|
end case;
|
Line 1187... |
Line 1207... |
when x"C" => -------------------------------------------------------------------------------- PUSHX instruction
|
when x"C" => -------------------------------------------------------------------------------- PUSHX instruction
|
when x"D" => --------------------------------------------------------------------------------- POPX instruction
|
when x"D" => --------------------------------------------------------------------------------- POPX instruction
|
when x"F" =>
|
when x"F" =>
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
when others => ------------------------------------------------------------- ER2,ER1 addressing mode instructions
|
when others => ------------------------------------------------------------- ER2,ER1 addressing mode instructions
|
MAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+1)) & IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+1)) & IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
end case;
|
end case;
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
------------------------------------------------------------------------------------------------ CPC R2,R1 instruction
|
------------------------------------------------------------------------------------------------ CPC R2,R1 instruction
|
TEMP_OP := ALU_CPC;
|
TEMP_OP := ALU_CPC;
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A4") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A4") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
----------------------------------------------------------------------------------------------- CPC IR2,R1 instruction
|
----------------------------------------------------------------------------------------------- CPC IR2,R1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A5") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A5") then
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
----------------------------------------------------------------------------------------------- CPC R1,IMM instruction
|
----------------------------------------------------------------------------------------------- CPC R1,IMM instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A6") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A6") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
---------------------------------------------------------------------------------------------- CPC IR1,IMM instruction
|
---------------------------------------------------------------------------------------------- CPC IR1,IMM instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A7") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A7") then
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
|
NUM_BYTES := 4;
|
NUM_BYTES := 4;
|
CPU_STATE := CPU_IND1;
|
CPU_STATE := CPU_IND1;
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 1229... |
Line 1249... |
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 3-byte instructions --
|
-- 3-byte instructions --
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
if (IQUEUE.CNT>=3) then
|
if (IQUEUE.CNT>=3) then -- 3-byte instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"D") then -------------------------------------------------- JP cc,DirectAddress
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"D") then -------------------------------------------------- JP cc,DirectAddress
|
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
|
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
|
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
else
|
else
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
end if;
|
end if;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then -------------------------------------------- column 9 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then -------------------------------------------- column 9 instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX rr1,r2,X instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX rr1,r2,X instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_XRRD;
|
CPU_STATE := CPU_XRRD;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then ------------------------------------ LEA rr1,rr2,X instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then ------------------------------------ LEA rr1,rr2,X instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_XRRTORR;
|
CPU_STATE := CPU_XRRTORR;
|
end if;
|
end if;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX r1,rr2,X instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then ----------------------------------------- LDX r1,rr2,X instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_XRRS;
|
CPU_STATE := CPU_XRRS;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then -------------------------------------- LEA r1,r2,X instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then -------------------------------------- LEA r1,r2,X instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_XRTOM;
|
CPU_STATE := CPU_XRTOM;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"C") then ---------------------------------------- PUSHX ER2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"C") then ---------------------------------------- PUSHX ER2 instruction
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
FRAB <= ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
DEST_ADDR := SP;
|
DEST_ADDR := SP;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"D") then ----------------------------------------- POPX ER2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"D") then ----------------------------------------- POPX ER2 instruction
|
MAB <= SP;
|
FRAB <= SP;
|
DEST_ADDR := ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
DEST_ADDR := ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
|
SP := SP + 1;
|
SP := SP + 1;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
end if;
|
end if;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"7") then -------------------------------------------- column 7 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"7") then -------------------------------------------- column 7 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => ------------------------------------------------------------------------- LDX IRR2,IR1 instruction
|
when x"8" => ------------------------------------------------------------------------- LDX IRR2,IR1 instruction
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IRRS;
|
CPU_STATE := CPU_IRRS;
|
when x"9" => ------------------------------------------------------------------------- LDX IR2,IRR1 instruction
|
when x"9" => ------------------------------------------------------------------------- LDX IR2,IRR1 instruction
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IMTOIRR;
|
CPU_STATE := CPU_IMTOIRR;
|
when x"C" => --------------------------------------------------------------------------- LD r1,r2,X instruction
|
when x"C" => --------------------------------------------------------------------------- LD r1,r2,X instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT = offset (X)
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_XADTOM;
|
CPU_STATE := CPU_XADTOM;
|
when x"D" => --------------------------------------------------------------------------- LD r2,r1,X instruction
|
when x"D" => --------------------------------------------------------------------------- LD r2,r1,X instruction
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
DEST_ADDR := RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
DEST_ADDR := RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_MTOXAD;
|
CPU_STATE := CPU_MTOXAD;
|
when x"F" => ------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
|
when x"F" => ------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
|
when others => ----------------------------------------------------------------------------- IR1,imm instructions
|
when others => ----------------------------------------------------------------------------- IR1,imm instructions
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IND1;
|
CPU_STATE := CPU_IND1;
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"6") then -------------------------------------------- column 6 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"6") then -------------------------------------------- column 6 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => -------------------------------------------------------------------------- LDX IRR2,R1 instruction
|
when x"8" => -------------------------------------------------------------------------- LDX IRR2,R1 instruction
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
LU_INSTRUCTION := '1'; -- in this mode this flag is used to signal the direct register addressing mode
|
LU_INSTRUCTION := '1'; -- in this mode this flag is used to signal the direct register addressing mode
|
CPU_STATE := CPU_IRRS;
|
CPU_STATE := CPU_IRRS;
|
when x"9" => -------------------------------------------------------------------------- LDX R2,IRR1 instruction
|
when x"9" => -------------------------------------------------------------------------- LDX R2,IRR1 instruction
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_MTOIRR;
|
CPU_STATE := CPU_MTOIRR;
|
when x"C" => -- illegal, decoded at 1-byte decoder
|
when x"C" => -- illegal, decoded at 1-byte decoder
|
--CPU_STATE := CPU_ILLEGAL; -- uncommenting this adds +400 LEs to the design!!!
|
--CPU_STATE := CPU_ILLEGAL; -- uncommenting this adds +400 LEs to the design!!!
|
when x"D" => ------------------------------------------------------------------------------ CALL DA instruction
|
when x"D" => ------------------------------------------------------------------------------ CALL DA instruction
|
when x"F" => ------------------------------------------------------------------------- BTJ p,b,r1,X instruction
|
when x"F" => ------------------------------------------------------------------------- BTJ p,b,r1,X instruction
|
when others => ------------------------------------------------------------------------------ R1,imm instructions
|
when others => ------------------------------------------------------------------------------ R1,imm instructions
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"5") then -------------------------------------------- column 5 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"5") then -------------------------------------------- column 5 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => -------------------------------------------------------------------------- LDX Ir1,ER2 instruction
|
when x"8" => -------------------------------------------------------------------------- LDX Ir1,ER2 instruction
|
MAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IND2;
|
CPU_STATE := CPU_IND2;
|
when x"9" => -------------------------------------------------------------------------- LDX Ir2,ER1 instruction
|
when x"9" => -------------------------------------------------------------------------- LDX Ir2,ER1 instruction
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
when x"C" => ------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
|
when x"C" => ------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
|
when x"D" => ----------------------------------------------------------------------------- BSWAP R1 instruction
|
when x"D" => ----------------------------------------------------------------------------- BSWAP R1 instruction
|
when x"F" => ---------------------------------------------------------------------------- LD R2,IR1 instruction
|
when x"F" => ---------------------------------------------------------------------------- LD R2,IR1 instruction
|
when others => ------------------------------------------------------------------------------ IR2,R1 instructions
|
when others => ------------------------------------------------------------------------------ IR2,R1 instructions
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"4") then -------------------------------------------- column 4 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"4") then -------------------------------------------- column 4 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => --------------------------------------------------------------------------- LDX r1,ER2 instruction
|
when x"8" => --------------------------------------------------------------------------- LDX r1,ER2 instruction
|
MAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when x"9" => --------------------------------------------------------------------------- LDX r2,ER1 instruction
|
when x"9" => --------------------------------------------------------------------------- LDX r2,ER1 instruction
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
|
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when x"C" => ------------------------------------------------------------------------------ JP Irr1 instruction
|
when x"C" => ------------------------------------------------------------------------------ JP Irr1 instruction
|
when x"D" => ---------------------------------------------------------------------------- CALL Irr1 instruction
|
when x"D" => ---------------------------------------------------------------------------- CALL Irr1 instruction
|
when x"F" => ----------------------------------------------------------------------------- MULT RR1 instruction
|
when x"F" => ----------------------------------------------------------------------------- MULT RR1 instruction
|
when others => ------------------------------------------------------------------------------- R2,R1 instructions
|
when others => ------------------------------------------------------------------------------- R2,R1 instructions
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
end case;
|
end case;
|
end if;
|
end if;
|
------------------------------------------------------------------------------------------------- BTJ p,b,r1,X instruction
|
------------------------------------------------------------------------------------------------- BTJ p,b,r1,X instruction
|
------------------------------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
|
------------------------------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F6" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F7") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F6" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F7") then
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(0)='0') then CPU_STATE := CPU_BTJ; else CPU_STATE := CPU_IBTJ;
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(0)='0') then CPU_STATE := CPU_BTJ; else CPU_STATE := CPU_IBTJ;
|
end if;
|
end if;
|
---------------------------------------------------------------------------------------------------- LD R2,IR1 instruction
|
---------------------------------------------------------------------------------------------------- LD R2,IR1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F5") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F5") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IND2;
|
CPU_STATE := CPU_IND2;
|
------------------------------------------------------------------------------------------------------ CALL DA instruction
|
------------------------------------------------------------------------------------------------------ CALL DA instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D6") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D6") then
|
DEST_ADDR16 := PC + 3;
|
DEST_ADDR16 := PC + 3;
|
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
LU_INSTRUCTION := '0'; -- this is used to indicate wether the stacking is due to a CALL or INT, 0 for a CALL
|
LU_INSTRUCTION := '0'; -- this is used to indicate wether the stacking is due to a CALL or INT, 0 for a CALL
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_STACK;
|
CPU_STATE := CPU_STACK;
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
---------------------------------------------------------------------------------------------------- 2nd page instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
|
-------------------------------------------------------------------------------------------------- PUSH IM instruction
|
-------------------------------------------------------------------------------------------------- PUSH IM instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"70") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"70") then
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
------------------------------------------------------------------------------------------------ CPC r1,r2 instruction
|
------------------------------------------------------------------------------------------------ CPC r1,r2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A2") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A2") then
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
|
TEMP_OP := ALU_CPC;
|
TEMP_OP := ALU_CPC;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
----------------------------------------------------------------------------------------------- CPC r1,Ir2 instruction
|
----------------------------------------------------------------------------------------------- CPC r1,Ir2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A3") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A3") then
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4)); -- dest address
|
TEMP_OP := ALU_CPC;
|
TEMP_OP := ALU_CPC;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
--------------------------------------------------------------------------------------------------- SRL R1 instruction
|
--------------------------------------------------------------------------------------------------- SRL R1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C0") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C0") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
TEMP_OP := LU2_SRL;
|
TEMP_OP := LU2_SRL;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
-------------------------------------------------------------------------------------------------- SRL IR1 instruction
|
-------------------------------------------------------------------------------------------------- SRL IR1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C1") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C1") then
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
|
TEMP_OP := LU2_SRL;
|
TEMP_OP := LU2_SRL;
|
NUM_BYTES := 3;
|
NUM_BYTES := 3;
|
CPU_STATE := CPU_IND1;
|
CPU_STATE := CPU_IND1;
|
LU_INSTRUCTION := '1';
|
LU_INSTRUCTION := '1';
|
end if;
|
end if;
|
Line 1447... |
Line 1467... |
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 2-byte instructions --
|
-- 2-byte instructions --
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
if (IQUEUE.CNT>=2) then
|
if (IQUEUE.CNT>=2) then -- 2-byte instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"C") then ------------------------------------------------- LD r,IMM instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"C") then ------------------------------------------------- LD r,IMM instruction
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
|
DATAWRITE(RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4),IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DATAWRITE(ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)),IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"B") then -------------------------------------------- JR cc,RelativeAddress
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"B") then -------------------------------------------- JR cc,RelativeAddress
|
PC := PC + 2;
|
PC := PC + 2;
|
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
|
if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
|
Line 1464... |
Line 1484... |
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
|
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
|
IQUEUE.CNT := IQUEUE.CNT - 2;
|
IQUEUE.CNT := IQUEUE.CNT - 2;
|
end if;
|
end if;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"A") then ------------------------------------------- DJNZ r,RelativeAddress
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"A") then ------------------------------------------- DJNZ r,RelativeAddress
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
|
PC := PC + 2;
|
PC := PC + 2;
|
DEST_ADDR16 := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR16 := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
|
IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
|
IQUEUE.CNT := IQUEUE.CNT - 2;
|
IQUEUE.CNT := IQUEUE.CNT - 2;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
Line 1477... |
Line 1497... |
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => ------------------------------------------------------------------------ LDEI Ir1,Irr2 instruction
|
when x"8" => ------------------------------------------------------------------------ LDEI Ir1,Irr2 instruction
|
when x"9" => ------------------------------------------------------------------------ LDEI Ir2,Irr1 instruction
|
when x"9" => ------------------------------------------------------------------------ LDEI Ir2,Irr1 instruction
|
when x"C" => ------------------------------------------------------------------------ LDCI Ir1,Irr2 instruction
|
when x"C" => ------------------------------------------------------------------------ LDCI Ir1,Irr2 instruction
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
LU_INSTRUCTION := '0'; -- indicates it is a read from program memory
|
LU_INSTRUCTION := '0'; -- indicates it is a read from program memory
|
WORD_DATA := '1'; -- indicates it is a LDCI instruction
|
WORD_DATA := '1'; -- indicates it is a LDCI instruction
|
CPU_STATE := CPU_LDPTOIM;
|
CPU_STATE := CPU_LDPTOIM;
|
when x"D" => ------------------------------------------------------------------------ LDCI Ir2,Irr1 instruction
|
when x"D" => ------------------------------------------------------------------------ LDCI Ir2,Irr1 instruction
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
LU_INSTRUCTION := '1'; -- indicates it is a write onto program memory
|
LU_INSTRUCTION := '1'; -- indicates it is a write onto program memory
|
WORD_DATA := '1'; -- indicates it is a LDCI instruction
|
WORD_DATA := '1'; -- indicates it is a LDCI instruction
|
CPU_STATE := CPU_LDPTOIM;
|
CPU_STATE := CPU_LDPTOIM;
|
when x"F" => ---------------------------------------------------------------------------- LD Ir1,r2 instruction
|
when x"F" => ---------------------------------------------------------------------------- LD Ir1,r2 instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_IND2;
|
CPU_STATE := CPU_IND2;
|
when others => --------------------------------------------------------------------------- Ir2 to r1 instructions
|
when others => --------------------------------------------------------------------------- Ir2 to r1 instructions
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"2") then -------------------------------------------- column 2 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"2") then -------------------------------------------- column 2 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => -------------------------------------------------------------------------- LDE r1,Irr2 instruction
|
when x"8" => -------------------------------------------------------------------------- LDE r1,Irr2 instruction
|
when x"9" => -------------------------------------------------------------------------- LDE r2,Irr1 instruction
|
when x"9" => -------------------------------------------------------------------------- LDE r2,Irr1 instruction
|
when x"C" => -------------------------------------------------------------------------- LDC r1,Irr2 instruction
|
when x"C" => -------------------------------------------------------------------------- LDC r1,Irr2 instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
LU_INSTRUCTION := '0';
|
LU_INSTRUCTION := '0';
|
CPU_STATE := CPU_LDPTOM;
|
CPU_STATE := CPU_LDPTOM;
|
when x"D" => -------------------------------------------------------------------------- LDC r2,Irr1 instruction
|
when x"D" => -------------------------------------------------------------------------- LDC r2,Irr1 instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
LU_INSTRUCTION := '1';
|
LU_INSTRUCTION := '1';
|
CPU_STATE := CPU_LDPTOM;
|
CPU_STATE := CPU_LDPTOM;
|
when x"E" => --------------------------------------------------------------------------- BIT p,b,r1 instruction
|
when x"E" => --------------------------------------------------------------------------- BIT p,b,r1 instruction
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4); -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
|
RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2); -- RESULT has the offset X
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_BIT;
|
CPU_STATE := CPU_BIT;
|
when x"F" => ----------------------------------------------------------------------------- TRAP imm instruction
|
when x"F" => ----------------------------------------------------------------------------- TRAP imm instruction
|
MAB <= "000" & IQUEUE.QUEUE(IQUEUE.RDPOS+1) & '0';
|
FRAB <= "000" & IQUEUE.QUEUE(IQUEUE.RDPOS+1) & '0';
|
DEST_ADDR16 := PC + 2;
|
DEST_ADDR16 := PC + 2;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_TRAP;
|
CPU_STATE := CPU_TRAP;
|
when others => ---------------------------------------------------------------------------- r2 to r1 instructions
|
when others => ---------------------------------------------------------------------------- r2 to r1 instructions
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0)); -- source address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4)); -- dest address
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
end case;
|
end case;
|
Line 1546... |
Line 1566... |
when x"0" => ------------------------------------------------------------------------------ SRP IMM instruction
|
when x"0" => ------------------------------------------------------------------------------ SRP IMM instruction
|
RP := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
RP := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when x"5" => ------------------------------------------------------------------------------ POP IR1 instruction
|
when x"5" => ------------------------------------------------------------------------------ POP IR1 instruction
|
MAB <= SP;
|
FRAB <= SP;
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
SP := SP + 1;
|
SP := SP + 1;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_IND2;
|
CPU_STATE := CPU_IND2;
|
when x"7" => ----------------------------------------------------------------------------- PUSH IR1 instruction
|
when x"7" => ----------------------------------------------------------------------------- PUSH IR1 instruction
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := SP;
|
DEST_ADDR := SP;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_ISMD1;
|
CPU_STATE := CPU_ISMD1;
|
when x"8" => --------------------------------------------------------------------------------- DECW instruction
|
when x"8" => --------------------------------------------------------------------------------- DECW instruction
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := LU2_DEC;
|
TEMP_OP := LU2_DEC;
|
WORD_DATA := '1';
|
WORD_DATA := '1';
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_INDRR;
|
CPU_STATE := CPU_INDRR;
|
when x"A" => --------------------------------------------------------------------------------- INCW instruction
|
when x"A" => --------------------------------------------------------------------------------- INCW instruction
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := LU2_INC;
|
TEMP_OP := LU2_INC;
|
WORD_DATA := '1';
|
WORD_DATA := '1';
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_INDRR;
|
CPU_STATE := CPU_INDRR;
|
when others => --------------------------------------------------------------------------------- IR1 instructions
|
when others => --------------------------------------------------------------------------------- IR1 instructions
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_IND1;
|
CPU_STATE := CPU_IND1;
|
LU_INSTRUCTION := '1';
|
LU_INSTRUCTION := '1';
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"0") then -------------------------------------------- column 0 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"0") then -------------------------------------------- column 0 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"0" => ---------------------------------------------------------------------------------- BRK instruction
|
when x"0" => ---------------------------------------------------------------------------------- BRK instruction
|
-- do nothing, BRK decoding is done in 1-byte instruction section
|
-- do nothing, BRK decoding is done in 1-byte instruction section
|
when x"5" => ---------------------------------------------------------------------------------- POP instruction
|
when x"5" => ---------------------------------------------------------------------------------- POP instruction
|
MAB <= SP;
|
FRAB <= SP;
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
SP := SP + 1;
|
SP := SP + 1;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when x"7" => --------------------------------------------------------------------------------- PUSH instruction
|
when x"7" => --------------------------------------------------------------------------------- PUSH instruction
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := SP;
|
DEST_ADDR := SP;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when x"8" => --------------------------------------------------------------------------------- DECW instruction
|
when x"8" => --------------------------------------------------------------------------------- DECW instruction
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
MAB <= DEST_ADDR+1;
|
FRAB <= DEST_ADDR+1;
|
TEMP_OP := LU2_DEC;
|
TEMP_OP := LU2_DEC;
|
WORD_DATA := '1';
|
WORD_DATA := '1';
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
when x"A" => --------------------------------------------------------------------------------- INCW instruction
|
when x"A" => --------------------------------------------------------------------------------- INCW instruction
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
MAB <= DEST_ADDR+1;
|
FRAB <= DEST_ADDR+1;
|
TEMP_OP := LU2_INC;
|
TEMP_OP := LU2_INC;
|
WORD_DATA := '1';
|
WORD_DATA := '1';
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
when others => ---------------------------------------------------------------------------------- R1 instructions
|
when others => ---------------------------------------------------------------------------------- R1 instructions
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
end case;
|
end case;
|
end if;
|
end if;
|
---------------------------------------------------------------------------------------------------------- MUL instruction
|
---------------------------------------------------------------------------------------------------------- MUL instruction
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F4") then
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F4") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_MUL;
|
CPU_STATE := CPU_MUL;
|
---------------------------------------------------------------------------------------------------- CALL IRR1 instruction
|
---------------------------------------------------------------------------------------------------- CALL IRR1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D4") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D4") then
|
DEST_ADDR16 := PC + 2;
|
DEST_ADDR16 := PC + 2;
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_INDSTACK;
|
CPU_STATE := CPU_INDSTACK;
|
------------------------------------------------------------------------------------------------------ JP IRR1 instruction
|
------------------------------------------------------------------------------------------------------ JP IRR1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C4") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C4") then
|
MAB <= RP(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+1);
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_INDJUMP;
|
CPU_STATE := CPU_INDJUMP;
|
----------------------------------------------------------------------------------------------------- BSWAP R1 instruction
|
----------------------------------------------------------------------------------------------------- BSWAP R1 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D5") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D5") then
|
MAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
TEMP_OP := ALU_BSWAP;
|
TEMP_OP := ALU_BSWAP;
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CPU_STATE := CPU_OMA;
|
CPU_STATE := CPU_OMA;
|
------------------------------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
|
------------------------------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C5") then
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C5") then
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
|
MAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
|
NUM_BYTES := 2;
|
NUM_BYTES := 2;
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
LU_INSTRUCTION := '0';
|
LU_INSTRUCTION := '0';
|
CPU_STATE := CPU_LDPTOIM;
|
CPU_STATE := CPU_LDPTOIM;
|
end if;
|
end if;
|
Line 1651... |
Line 1671... |
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 1-byte instructions --
|
-- 1-byte instructions --
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
if (IQUEUE.CNT>=1) then
|
if (IQUEUE.CNT>=1) then -- 1-byte instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"F") then ------------------------------------------------ column F instructions
|
if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"F") then ------------------------------------------------ column F instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"0" => ---------------------------------------------------------------------------------- NOP instruction
|
when x"0" => ---------------------------------------------------------------------------------- NOP instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"1" => ------------------------------------------------------------------------------ page 2 instructions
|
when x"1" => ------------------------------------------------------------------------------ page 2 instructions
|
Line 1668... |
Line 1688... |
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
when x"5" => ---------------------------------------------------------------------------------- WDT instruction
|
when x"5" => ---------------------------------------------------------------------------------- WDT instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"6" => --------------------------------------------------------------------------------- STOP instruction
|
when x"6" => --------------------------------------------------------------------------------- STOP instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
CPU_STATE := CPU_HALTED;
|
|
STOP <= '1';
|
STOP <= '1';
|
when x"7" => --------------------------------------------------------------------------------- HALT instruction
|
when x"7" => --------------------------------------------------------------------------------- HALT instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
CPU_STATE := CPU_HALTED;
|
HALT := '1';
|
when x"8" => ----------------------------------------------------------------------------------- DI instruction
|
when x"8" => ----------------------------------------------------------------------------------- DI instruction
|
IRQE := '0';
|
IRQE := '0';
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"9" => ----------------------------------------------------------------------------------- EI instruction
|
when x"9" => ----------------------------------------------------------------------------------- EI instruction
|
IRQE := '1';
|
IRQE := '1';
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"A" => ---------------------------------------------------------------------------------- RET instruction
|
when x"A" => ---------------------------------------------------------------------------------- RET instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
MAB <= SP;
|
FRAB <= SP;
|
CPU_STATE := CPU_UNSTACK;
|
CPU_STATE := CPU_UNSTACK2;
|
when x"B" => --------------------------------------------------------------------------------- IRET instruction
|
when x"B" => --------------------------------------------------------------------------------- IRET instruction
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
IRQE := '1';
|
IRQE := '1';
|
MAB <= SP;
|
FRAB <= SP;
|
CPU_STATE := CPU_UNSTACK3;
|
CPU_STATE := CPU_UNSTACK3;
|
when x"C" => ---------------------------------------------------------------------------------- RCF instruction
|
when x"C" => ---------------------------------------------------------------------------------- RCF instruction
|
CPU_FLAGS.C := '0';
|
CPU_FLAGS.C := '0';
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"D" => ---------------------------------------------------------------------------------- SCF instruction
|
when x"D" => ---------------------------------------------------------------------------------- SCF instruction
|
Line 1701... |
Line 1720... |
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when others => ---------------------------------------------------------------------------------- R1 instructions
|
when others => ---------------------------------------------------------------------------------- R1 instructions
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
end case;
|
end case;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"E") then ------------------------------------------------ INC r instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"E") then ------------------------------------------------ INC r instruction
|
MAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
|
TEMP_OP := LU2_INC;
|
TEMP_OP := LU2_INC;
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"00") then -------------------------------------------------------------- BRK instruction
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"00") then -------------------------------------------------------------- BRK instruction
|
if (OCDCR.BRKEN='1') then -- the BRK instruction is enabled
|
if (OCDCR.BRKEN='1') then -- the BRK instruction is enabled
|
Line 1725... |
Line 1744... |
IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F8" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C6") then --------------------------- illegal opcode
|
IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F8" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C6") then --------------------------- illegal opcode
|
CPU_STATE:= CPU_ILLEGAL;
|
CPU_STATE:= CPU_ILLEGAL;
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if; -- if DBGMODE=0...
|
PC := PC + NUM_BYTES;
|
end if; -- if not stopped or halted
|
IQUEUE.RDPOS := IQUEUE.RDPOS + NUM_BYTES;
|
PC := PC + NUM_BYTES; -- update PC after instruction
|
IQUEUE.CNT := IQUEUE.CNT - NUM_BYTES;
|
IQUEUE.RDPOS := IQUEUE.RDPOS + NUM_BYTES; -- update QUEUE read pointer
|
if (OCD.SINGLESTEP='1') then
|
IQUEUE.CNT := IQUEUE.CNT - NUM_BYTES; -- update QUEUE available bytes
|
if (NUM_BYTES/=0 or IQUEUE.FETCH_STATE=F_ADDR) then OCD.SINGLESTEP:='0';
|
if (OCD.SINGLESTEP='1') then -- if we are stepping instructions
|
|
if (NUM_BYTES/=0 or IQUEUE.FETCH_STATE=F_ADDR) then OCD.SINGLESTEP:='0'; -- if a instruction was decoded, reset step flag
|
end if;
|
end if;
|
end if;
|
end if;
|
when CPU_MUL => -- MUL ***********************************************************************************************************
|
when CPU_MUL => -- MUL ***********************************************************************************************************
|
TEMP_DATA := DATAREAD(MAB); -- read first operand
|
TEMP_DATA := DATAREAD(FRAB); -- read first operand
|
MAB <= MAB + 1; -- go to the next operand
|
FRAB <= FRAB + 1; -- go to the next operand
|
CPU_STATE := CPU_MUL1;
|
CPU_STATE := CPU_MUL1;
|
when CPU_MUL1 =>
|
when CPU_MUL1 =>
|
DEST_ADDR16 := TEMP_DATA * DATAREAD(MAB); -- multiply previous operand by the second operand and store temporarily
|
DEST_ADDR16 := TEMP_DATA * DATAREAD(FRAB); -- multiply previous operand by the second operand and store temporarily
|
DATAWRITE(MAB,DEST_ADDR16(7 downto 0)); -- write the lower byte in current memory address
|
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- prepare to write the lower byte in current memory address
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_MUL2;
|
CPU_STATE := CPU_MUL2;
|
when CPU_MUL2 =>
|
when CPU_MUL2 =>
|
MAB <= MAB - 1; -- decrement memory address (point to the first operand)
|
FRAB <= FRAB - 1; -- decrement memory address (point to the first operand)
|
DATAWRITE(MAB,DEST_ADDR16(15 downto 8)); -- write the higher byte
|
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8)); -- write the higher byte
|
CPU_STATE := CPU_STORE; -- complete store operation
|
CPU_STATE := CPU_STORE; -- complete store operation
|
when CPU_XRRTORR => -- LEA *******************************************************************************************************
|
when CPU_XRRTORR => -- LEA *******************************************************************************************************
|
TEMP_DATA := DATAREAD(MAB); -- read the operand and store it
|
TEMP_DATA := DATAREAD(FRAB); -- read the operand and store it
|
MAB <= MAB + 1; -- go to the next memory address
|
FRAB <= FRAB + 1; -- go to the next memory address
|
CPU_STATE := CPU_XRRTORR2;
|
CPU_STATE := CPU_XRRTORR2;
|
when CPU_XRRTORR2 =>
|
when CPU_XRRTORR2 =>
|
-- read the next operand and perform a 16 bit add with the offset previously in result
|
-- read next operand and perform a 16 bit add with the offset previously in result
|
DEST_ADDR16 := ADDER16(TEMP_DATA & DATAREAD(MAB),RESULT);
|
DEST_ADDR16 := ADDER16(TEMP_DATA & DATAREAD(FRAB),RESULT);
|
MAB <= DEST_ADDR; -- point to the destination address
|
FRAB <= DEST_ADDR; -- point to the destination address
|
DATAWRITE(MAB,DEST_ADDR16(15 downto 8)); -- store the higher byte of the 16-bit result
|
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8)); -- store the higher byte of the 16-bit result
|
CPU_STATE := CPU_XRRTORR3;
|
CPU_STATE := CPU_XRRTORR3;
|
when CPU_XRRTORR3 =>
|
when CPU_XRRTORR3 =>
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_XRRTORR4;
|
CPU_STATE := CPU_XRRTORR4;
|
when CPU_XRRTORR4 =>
|
when CPU_XRRTORR4 =>
|
MAB <= MAB + 1; -- go to the next memory address
|
FRAB <= FRAB + 1; -- go to the next memory address
|
DATAWRITE(MAB,DEST_ADDR16(7 downto 0)); -- store the lower byte of the 16-bit result
|
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- store the lower byte of the 16-bit result
|
CPU_STATE := CPU_STORE; -- complete store operation
|
CPU_STATE := CPU_STORE; -- complete store operation
|
when CPU_MTOXAD => -- MEMORY TO INDEXED 8-BIT ADDRESS ***************************************************************************
|
when CPU_MTOXAD => -- MEMORY TO INDEXED 8-BIT ADDRESS ***************************************************************************
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB); -- read operand from memory
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR; -- update address bus with destination address
|
CPU_STATE := CPU_MTOXAD2;
|
CPU_STATE := CPU_MTOXAD2;
|
when CPU_MTOXAD2 =>
|
when CPU_MTOXAD2 =>
|
MAB <= RP(3 downto 0)&(DATAREAD(MAB) + RESULT);
|
FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT); -- update address bus indexed result
|
DATAWRITE(MAB,TEMP_DATA);
|
DATAWRITE(FRAB,TEMP_DATA); -- prepare to write data on destination (indexed) address
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE; -- perform store (WR=1)
|
when CPU_XADTOM => -- INDEXED 8-BIT ADDRESS TO MEMORY ***************************************************************************
|
when CPU_XADTOM => -- INDEXED 8-BIT ADDRESS TO MEMORY ***************************************************************************
|
MAB <= RP(3 downto 0)&(DATAREAD(MAB) + RESULT);
|
FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT);
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when CPU_XRTOM => -- LEA *******************************************************************************************************
|
when CPU_XRTOM => -- LEA *******************************************************************************************************
|
TEMP_DATA := DATAREAD(MAB)+RESULT;
|
TEMP_DATA := DATAREAD(FRAB)+RESULT;
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR;
|
DATAWRITE(MAB,TEMP_DATA);
|
DATAWRITE(FRAB,TEMP_DATA);
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE;
|
when CPU_IMTOIRR => -- INDIRECT MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ***********************************************
|
when CPU_IMTOIRR => -- INDIRECT MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ***********************************************
|
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- source address is read from indirect register
|
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
|
CPU_STATE := CPU_MTOIRR;
|
CPU_STATE := CPU_MTOIRR;
|
when CPU_MTOIRR => -- MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ********************************************************
|
when CPU_MTOIRR => -- MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ********************************************************
|
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
|
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
|
MAB <= DEST_ADDR; -- MAB points to the indirect destination register pair
|
FRAB <= DEST_ADDR; -- FRAB points to the indirect destination register pair
|
RESULT := x"00";
|
RESULT := x"00";
|
CPU_STATE := CPU_XRRD2; -- proceed as X indexed register pair destination
|
CPU_STATE := CPU_XRRD2; -- proceed as X indexed register pair destination
|
when CPU_IRRS => -- RR PAIR AS INDIRECT SOURCE ADDRESS ************************************************************************
|
when CPU_IRRS => -- RR PAIR AS INDIRECT SOURCE ADDRESS ************************************************************************
|
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
|
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE := CPU_IRRS2;
|
CPU_STATE := CPU_IRRS2;
|
when CPU_IRRS2 =>
|
when CPU_IRRS2 =>
|
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
|
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
|
MAB <= DEST_ADDR16(11 downto 0);
|
FRAB <= DEST_ADDR16(11 downto 0);
|
if (LU_INSTRUCTION='1') then
|
if (LU_INSTRUCTION='1') then
|
CPU_STATE:= CPU_TMA; -- if it is direct addressing mode, go to TMA
|
CPU_STATE:= CPU_TMA; -- if it is direct addressing mode, go to TMA
|
else
|
else
|
CPU_STATE := CPU_IND2; -- if it is indirect addressing mode, go to IND2
|
CPU_STATE := CPU_IND2; -- if it is indirect addressing mode, go to IND2
|
end if;
|
end if;
|
when CPU_XRRD =>
|
when CPU_XRRD => -- RR PAIR PLUS OFFSET AS DESTINATION ADDRESS ****************************************************************
|
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
|
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR;
|
CPU_STATE := CPU_XRRD2;
|
CPU_STATE := CPU_XRRD2;
|
when CPU_XRRD2 =>
|
when CPU_XRRD2 =>
|
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
|
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE := CPU_XRRD3;
|
CPU_STATE := CPU_XRRD3;
|
when CPU_XRRD3 =>
|
when CPU_XRRD3 =>
|
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
|
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
|
MAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
|
FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
|
DATAWRITE(MAB,TEMP_DATA);
|
DATAWRITE(FRAB,TEMP_DATA);
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE;
|
when CPU_XRRS =>
|
when CPU_XRRS => -- RR PAIR PLUS OFFSET AS SOURCE ADDRESS *********************************************************************
|
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
|
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE := CPU_XRRS2;
|
CPU_STATE := CPU_XRRS2;
|
when CPU_XRRS2 =>
|
when CPU_XRRS2 =>
|
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
|
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
|
MAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
|
FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
|
CPU_STATE := CPU_XRRS3;
|
CPU_STATE := CPU_XRRS3;
|
when CPU_XRRS3 =>
|
when CPU_XRRS3 =>
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR;
|
DATAWRITE(MAB,TEMP_DATA);
|
DATAWRITE(FRAB,TEMP_DATA);
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE;
|
when CPU_INDRR => -- INDIRECT DESTINATION ADDRESS FOR WORD INSTRUCTIONS (DECW AND INCW) ****************************************
|
when CPU_INDRR => -- INDIRECT DESTINATION ADDRESS FOR WORD INSTRUCTIONS (DECW AND INCW) ****************************************
|
MAB <= (RP(3 downto 0) & DATAREAD(MAB))+1; -- the destination address is given by indirect address
|
FRAB <= (RP(3 downto 0) & DATAREAD(FRAB))+1; -- the destination address is given by indirect address
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
when CPU_ISMD1 => -- INDIRECT SOURCE ADDRESS ***********************************************************************************
|
when CPU_ISMD1 => -- INDIRECT SOURCE ADDRESS ***********************************************************************************
|
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- source address is read from indirect register
|
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
|
CPU_STATE := CPU_TMA;
|
CPU_STATE := CPU_TMA;
|
when CPU_IND2 => -- READS REGISTER AND PERFORM OPERATION ON AN INDIRECT DESTINATION *******************************************
|
when CPU_IND2 => -- READS REGISTER AND PERFORM OPERATION ON AN INDIRECT DESTINATION *******************************************
|
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
|
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
|
MAB <= DEST_ADDR; -- place the address of the indirect register on MAB
|
FRAB <= DEST_ADDR; -- place the address of the indirect register on FRAB
|
CPU_STATE := CPU_IND1; -- proceed to the indirect
|
CPU_STATE := CPU_IND1; -- proceed to the indirect
|
when CPU_IND1 => -- INDIRECT DESTINATION ADDRESS ******************************************************************************
|
when CPU_IND1 => -- INDIRECT DESTINATION ADDRESS ******************************************************************************
|
MAB <= RP(3 downto 0) & DATAREAD(MAB); -- the destination address is given by indirect address
|
FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- the destination address is given by indirect address
|
if (LU_INSTRUCTION='0') then CPU_STATE := CPU_OMA; -- proceed with one memory access
|
if (LU_INSTRUCTION='0') then CPU_STATE := CPU_OMA; -- proceed with one memory access
|
else CPU_STATE := CPU_OMA2; -- proceed with one memory access (logic unit related)
|
else CPU_STATE := CPU_OMA2; -- proceed with one memory access (logic unit related)
|
end if;
|
end if;
|
when CPU_TMA => -- TWO MEMORY ACCESS, READS SOURCE OPERAND FROM MEMORY *******************************************************
|
when CPU_TMA => -- TWO MEMORY ACCESS, READS SOURCE OPERAND FROM MEMORY *******************************************************
|
TEMP_DATA := DATAREAD(MAB); -- reads data from the source (MAB) address and store it into TEMP_DATA
|
TEMP_DATA := DATAREAD(FRAB); -- reads data from the source (FRAB) address and store it into TEMP_DATA
|
MAB <= DEST_ADDR; -- place the destination address (DEST_ADDR) on the memory address bus (MAB)
|
FRAB <= DEST_ADDR; -- place destination address (DEST_ADDR) on memory address bus (FRAB)
|
CPU_STATE := CPU_OMA; -- proceed to the last stage
|
CPU_STATE := CPU_OMA; -- proceed to the last stage
|
when CPU_OMA => -- ONE MEMORY ACCESS stage ***********************************************************************************
|
when CPU_OMA => -- ONE MEMORY ACCESS stage ***********************************************************************************
|
-- this stage performs the TEMP_OP operation between TEMP_DATA and data read from current (MAB) address (destination)
|
-- this stage performs TEMP_OP operation between TEMP_DATA and data read from current (FRAB) address (destination)
|
RESULT := ALU(TEMP_OP,DATAREAD(MAB),TEMP_DATA,CPU_FLAGS.C);
|
RESULT := ALU(TEMP_OP,DATAREAD(FRAB),TEMP_DATA,CPU_FLAGS.C);
|
if (TEMP_OP<ALU_OR) then
|
if (TEMP_OP<ALU_OR) then
|
CPU_FLAGS.C := ALU_FLAGS.C;
|
CPU_FLAGS.C := ALU_FLAGS.C;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
Line 1865... |
Line 1885... |
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.V := '0';
|
CPU_FLAGS.V := '0';
|
end if;
|
end if;
|
if (ALU_NOUPDATE='0') then
|
if (ALU_NOUPDATE='0') then
|
DATAWRITE(MAB,RESULT);
|
DATAWRITE(FRAB,RESULT);
|
WR <= '1';
|
WR <= '1';
|
end if;
|
end if;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
if (WORD_DATA='1') then
|
if (WORD_DATA='1') then
|
CPU_STATE := CPU_LDW;
|
CPU_STATE := CPU_LDW;
|
end if;
|
end if;
|
when CPU_OMA2 => -- ONE MEMORY ACCESS stage logic unit related ****************************************************************
|
when CPU_OMA2 => -- ONE MEMORY ACCESS stage logic unit related ****************************************************************
|
-- this stage performs the TEMP_OP LU2 operation on data read from current (MAB) address
|
-- this stage performs TEMP_OP LU2 operation on data read from current (FRAB) address
|
RESULT := LU2(TEMP_OP,DATAREAD(MAB),CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.C);
|
RESULT := LU2(TEMP_OP,DATAREAD(FRAB),CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.C);
|
if (TEMP_OP=LU2_DEC or TEMP_OP=LU2_INC) then
|
if (TEMP_OP=LU2_DEC or TEMP_OP=LU2_INC) then
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
elsif (TEMP_OP=LU2_COM) then
|
elsif (TEMP_OP=LU2_COM) then
|
Line 1900... |
Line 1920... |
CPU_FLAGS.C := ALU_FLAGS.C;
|
CPU_FLAGS.C := ALU_FLAGS.C;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.Z := ALU_FLAGS.Z;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
end if;
|
end if;
|
DATAWRITE(MAB,RESULT);
|
DATAWRITE(FRAB,RESULT);
|
WR <= '1';
|
WR <= '1';
|
if (WORD_DATA='1') then
|
if (WORD_DATA='1') then
|
WORD_DATA := '0';
|
WORD_DATA := '0';
|
if (ALU_FLAGS.C='0') then TEMP_OP := LU2_LD;
|
if (ALU_FLAGS.C='0') then TEMP_OP := LU2_LD;
|
end if;
|
end if;
|
CPU_STATE := CPU_DMAB;
|
CPU_STATE := CPU_DMAB;
|
else CPU_STATE := CPU_DECOD;
|
else CPU_STATE := CPU_DECOD;
|
end if;
|
end if;
|
when CPU_DMAB => -- DECREMENT MEMORY ADDRESS BUS *****************************************************************************
|
when CPU_DMAB => -- DECREMENT MEMORY ADDRESS BUS ******************************************************************************
|
MAB <= MAB - 1;
|
FRAB <= FRAB - 1;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
when CPU_LDW =>
|
when CPU_LDW => -- LOAD WORD INSTRUCTION *************************************************************************************
|
if (WORD_DATA='0') then
|
-- read higher byte from source operand
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
else
|
|
DATAWRITE(MAB,TEMP_DATA);
|
|
WR <= '1';
|
|
end if;
|
|
CPU_STATE := CPU_LDW2;
|
CPU_STATE := CPU_LDW2;
|
when CPU_LDW2 =>
|
when CPU_LDW2 =>
|
if (WORD_DATA='0') then
|
-- read lower byte from source operand
|
RESULT := DATAREAD(MAB);
|
RESULT := DATAREAD(FRAB);
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR;
|
WORD_DATA := '1';
|
CPU_STATE := CPU_LDW3;
|
CPU_STATE := CPU_LDW;
|
when CPU_LDW3 =>
|
else
|
-- write higher byte to destination operand
|
MAB <= MAB + 1;
|
DATAWRITE(FRAB,TEMP_DATA);
|
DATAWRITE(MAB,RESULT);
|
WR <= '1';
|
|
CPU_STATE := CPU_LDW4;
|
|
when CPU_LDW4 =>
|
|
-- points FRAB to lower byte of destination address
|
|
FRAB <= FRAB + 1;
|
|
CPU_STATE := CPU_LDW5;
|
|
when CPU_LDW5 =>
|
|
DATAWRITE(FRAB,RESULT);
|
CPU_STATE := CPU_STORE;
|
CPU_STATE := CPU_STORE;
|
end if;
|
|
when CPU_LDPTOIM => -- LOAD PROGRAM TO INDIRECT MEMORY **************************************************************************
|
when CPU_LDPTOIM => -- LOAD PROGRAM TO INDIRECT MEMORY **************************************************************************
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
DEST_ADDR := RP(3 downto 0) & TEMP_DATA; -- the destination address is read from the indirect address
|
DEST_ADDR := RP(3 downto 0) & TEMP_DATA; -- the destination address is read from the indirect address
|
if (WORD_DATA='1') then
|
if (WORD_DATA='1') then
|
-- it is a LDCI instruction, so we have to increment the indirect address after the operation
|
-- it is a LDCI instruction, so we have to increment the indirect address after the operation
|
DATAWRITE(MAB,TEMP_DATA+1);
|
DATAWRITE(FRAB,TEMP_DATA+1);
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_LDPTOIM2;
|
CPU_STATE := CPU_LDPTOIM2;
|
else
|
else
|
-- it is a LDC instruction, proceed the load instruction
|
-- it is a LDC instruction, proceed the load instruction
|
MAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
|
FRAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
|
CPU_STATE := CPU_LDPTOM;
|
CPU_STATE := CPU_LDPTOM;
|
end if;
|
end if;
|
when CPU_LDPTOIM2 =>
|
when CPU_LDPTOIM2 =>
|
MAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
|
FRAB <= ADDRESSER4(RESULT(3 downto 0)); -- the source address (program memory) is read from source register pair
|
CPU_STATE := CPU_LDPTOM;
|
CPU_STATE := CPU_LDPTOM;
|
when CPU_LDPTOM => -- LOAD PROGRAM TO MEMORY ***********************************************************************************
|
when CPU_LDPTOM => -- LOAD PROGRAM TO MEMORY ***********************************************************************************
|
IAB(15 downto 8) <= DATAREAD(MAB); -- read the high address from the first register
|
IAB(15 downto 8) <= DATAREAD(FRAB); -- read the high address from the first register
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE := CPU_LDPTOM2;
|
CPU_STATE := CPU_LDPTOM2;
|
when CPU_LDPTOM2 =>
|
when CPU_LDPTOM2 =>
|
IAB(7 downto 0) <= DATAREAD(MAB); -- read the low address from the second register
|
IAB(7 downto 0) <= DATAREAD(FRAB); -- read the low address from the second register
|
MAB <= DEST_ADDR;
|
FRAB <= DEST_ADDR;
|
if (LU_INSTRUCTION='0') then
|
if (LU_INSTRUCTION='0') then
|
CPU_STATE := CPU_LDPTOM3; -- if it is a read from program memory
|
CPU_STATE := CPU_LDPTOM3; -- if it is a read from program memory
|
else
|
else
|
CPU_STATE := CPU_LDMTOP; -- if it is a write onto program memory
|
CPU_STATE := CPU_LDMTOP; -- if it is a write onto program memory
|
end if;
|
end if;
|
when CPU_LDPTOM3 => -- READ PROGRAM MEMORY AND STORE INTO RAM *******************************************************************
|
when CPU_LDPTOM3 => -- READ PROGRAM MEMORY AND STORE INTO RAM *******************************************************************
|
DATAWRITE(MAB,IDB);
|
DATAWRITE(FRAB,IDB);
|
WR <= '1';
|
WR <= '1';
|
CAN_FETCH := '1'; -- re-enable fetching
|
CAN_FETCH := '1'; -- re-enable fetching
|
FETCH_ADDR := PC;
|
FETCH_ADDR := PC;
|
IAB <= PC;
|
IAB <= PC;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
if (WORD_DATA='1') then
|
if (WORD_DATA='1') then
|
CPU_STATE := CPU_LDPTOM4;
|
CPU_STATE := CPU_LDPTOM4;
|
end if;
|
end if;
|
when CPU_LDPTOM4 =>
|
when CPU_LDPTOM4 =>
|
DEST_ADDR := ADDRESSER4(RESULT(3 downto 0));
|
DEST_ADDR := ADDRESSER4(RESULT(3 downto 0));
|
MAB <= DEST_ADDR+1;
|
FRAB <= DEST_ADDR+1;
|
TEMP_OP := LU2_INC;
|
TEMP_OP := LU2_INC;
|
CPU_STATE := CPU_OMA2;
|
CPU_STATE := CPU_OMA2;
|
when CPU_LDMTOP => -- READ RAM AND STORE ONTO PROGRAM MEMORY *******************************************************************
|
when CPU_LDMTOP => -- READ RAM AND STORE ONTO PROGRAM MEMORY *******************************************************************
|
PWDB <= DATAREAD(MAB); -- PWDB receive the content of RAM
|
IWDB <= DATAREAD(FRAB); -- IWDB receive the content of RAM
|
PGM_WR <= '1'; -- enable program memory write signal
|
PGM_WR <= '1'; -- enable program memory write signal
|
CPU_STATE := CPU_LDMTOP2;
|
CPU_STATE := CPU_LDMTOP2;
|
when CPU_LDMTOP2 =>
|
when CPU_LDMTOP2 =>
|
CAN_FETCH := '1'; -- re-enable instruction fetching
|
CAN_FETCH := '1'; -- re-enable instruction fetching
|
FETCH_ADDR := PC;
|
FETCH_ADDR := PC;
|
IAB <= PC;
|
IAB <= PC;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
if (WORD_DATA='1') then
|
if (WORD_DATA='1') then
|
CPU_STATE := CPU_LDPTOM4;
|
CPU_STATE := CPU_LDPTOM4;
|
end if;
|
end if;
|
when CPU_BIT =>
|
when CPU_BIT => -- BIT INSTRUCTION *******************************************************************************************
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0)))):=TEMP_OP(3);
|
TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0)))):=TEMP_OP(3);
|
DATAWRITE(MAB,TEMP_DATA);
|
DATAWRITE(FRAB,TEMP_DATA);
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when CPU_IBTJ =>
|
when CPU_IBTJ => -- INDIRECT BIT TEST JUMP INSTRUCTION ************************************************************************
|
MAB <= RP(3 downto 0) & DATAREAD(MAB);
|
FRAB <= RP(3 downto 0) & DATAREAD(FRAB);
|
CPU_STATE := CPU_BTJ;
|
CPU_STATE := CPU_BTJ;
|
when CPU_BTJ =>
|
when CPU_BTJ => -- BIT TEST JUMP INSTRUCTION *********************************************************************************
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
if (TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0))))=TEMP_OP(3)) then
|
if (TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0))))=TEMP_OP(3)) then
|
PC := ADDER16(PC,RESULT);
|
PC := ADDER16(PC,RESULT);
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
end if;
|
end if;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when CPU_DJNZ =>
|
when CPU_DJNZ => -- DECREMENT AND JUMP IF NOT ZERO INSTRUCTION ****************************************************************
|
RESULT := LU2(LU2_DEC,DATAREAD(MAB),'0','0','0');
|
RESULT := LU2(LU2_DEC,DATAREAD(FRAB),'0','0','0');
|
if (ALU_FLAGS.Z='0') then -- result is not zero, then jump relative
|
if (ALU_FLAGS.Z='0') then -- result is not zero, then jump relative
|
PC := DEST_ADDR16;
|
PC := DEST_ADDR16;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
end if;
|
end if;
|
DATAWRITE(MAB,RESULT);
|
DATAWRITE(FRAB,RESULT);
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when CPU_INDJUMP =>
|
when CPU_INDJUMP => -- INDIRECT JUMP INSTRUCTION *********************************************************************************
|
PC(15 downto 8) := DATAREAD(MAB);
|
PC(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE:= CPU_INDJUMP2;
|
CPU_STATE:= CPU_INDJUMP2;
|
when CPU_INDJUMP2 =>
|
when CPU_INDJUMP2 =>
|
PC(7 downto 0) := DATAREAD(MAB);
|
PC(7 downto 0) := DATAREAD(FRAB);
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when CPU_TRAP =>
|
when CPU_TRAP => -- TRAP INSTRUCTION ******************************************************************************************
|
PC(15 downto 8) := DATAREAD(MAB);
|
PC(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE:= CPU_TRAP2;
|
CPU_STATE:= CPU_TRAP2;
|
when CPU_TRAP2 =>
|
when CPU_TRAP2 =>
|
PC(7 downto 0) := DATAREAD(MAB);
|
PC(7 downto 0) := DATAREAD(FRAB);
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
LU_INSTRUCTION := '1';
|
LU_INSTRUCTION := '1';
|
CPU_STATE := CPU_STACK;
|
CPU_STATE := CPU_STACK;
|
when CPU_INDSTACK =>
|
when CPU_INDSTACK => -- INDIRECT CALL INSTRUCTION *****************************************************************************
|
PC(15 downto 8) := DATAREAD(MAB);
|
PC(15 downto 8) := DATAREAD(FRAB);
|
MAB <= MAB + 1;
|
FRAB <= FRAB + 1;
|
CPU_STATE:= CPU_INDSTACK2;
|
CPU_STATE:= CPU_INDSTACK2;
|
when CPU_INDSTACK2 =>
|
when CPU_INDSTACK2 =>
|
PC(7 downto 0) := DATAREAD(MAB);
|
PC(7 downto 0) := DATAREAD(FRAB);
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_STACK;
|
CPU_STATE := CPU_STACK;
|
when CPU_VECTOR =>
|
when CPU_VECTOR => -- LOAD PC WITH ADDRESS STORED IN PROGRAM MEMORY *********************************************************
|
PC(15 downto 8) := IDB;
|
PC(15 downto 8) := IDB; -- read high byte of destination address
|
IAB <= IAB + 1;
|
IAB <= IAB + 1;
|
CPU_STATE := CPU_VECTOR2;
|
CPU_STATE := CPU_VECTOR2;
|
when CPU_VECTOR2 =>
|
when CPU_VECTOR2 =>
|
PC(7 downto 0) := IDB;
|
PC(7 downto 0) := IDB; -- read low byte of destination address
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR; -- reset queue FSM
|
CAN_FETCH := '1';
|
CAN_FETCH := '1'; -- restart fetching
|
if (LU_INSTRUCTION='1') then CPU_STATE := CPU_STACK;
|
if (INT_FLAG='1') then CPU_STATE := CPU_STACK;
|
else CPU_STATE := CPU_DECOD;
|
else CPU_STATE := CPU_DECOD;
|
end if;
|
end if;
|
when CPU_STACK => -- PUSH PC 7:0 INTO THE STACK *******************************************************************************
|
when CPU_STACK => -- PUSH PC 7:0 INTO THE STACK ********************************************************************************
|
DATAWRITE(MAB,DEST_ADDR16(7 downto 0));
|
DATAWRITE(FRAB,DEST_ADDR16(7 downto 0));
|
WR <= '1';
|
WR <= '1';
|
CPU_STATE := CPU_STACK1;
|
CPU_STATE := CPU_STACK1;
|
when CPU_STACK1 =>
|
when CPU_STACK1 =>
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
CPU_STATE := CPU_STACK2;
|
CPU_STATE := CPU_STACK2;
|
when CPU_STACK2 =>
|
when CPU_STACK2 => -- PUSH PC 15:8 INTO THE STACK *******************************************************************************
|
DATAWRITE(MAB,DEST_ADDR16(15 downto 8));
|
DATAWRITE(FRAB,DEST_ADDR16(15 downto 8));
|
WR <= '1';
|
WR <= '1';
|
if (LU_INSTRUCTION='1') then
|
if (INT_FLAG='1') then
|
CPU_STATE := CPU_STACK3;
|
CPU_STATE := CPU_STACK3;
|
else
|
else
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
end if;
|
end if;
|
when CPU_STACK3 => -- PUSH FLAGS INTO THE STACK *******************************************************************************
|
when CPU_STACK3 => -- PUSH FLAGS INTO THE STACK *********************************************************************************
|
SP := SP - 1;
|
SP := SP - 1;
|
MAB <= SP;
|
FRAB <= SP;
|
DATAWRITE(MAB,CPU_FLAGS.C&CPU_FLAGS.Z&CPU_FLAGS.S&CPU_FLAGS.V&CPU_FLAGS.D&CPU_FLAGS.H&CPU_FLAGS.F2&CPU_FLAGS.F1);
|
DATAWRITE(FRAB,CPU_FLAGS.C&CPU_FLAGS.Z&CPU_FLAGS.S&CPU_FLAGS.V&CPU_FLAGS.D&CPU_FLAGS.H&CPU_FLAGS.F2&CPU_FLAGS.F1);
|
WR <= '1';
|
|
IRQE := '0';
|
IRQE := '0';
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_STORE;
|
when CPU_UNSTACK3 =>
|
when CPU_UNSTACK3 => -- POP FLAGS FROM STACK **********************************************************************************
|
TEMP_DATA := DATAREAD(MAB);
|
TEMP_DATA := DATAREAD(FRAB);
|
CPU_FLAGS.C := TEMP_DATA(7);
|
CPU_FLAGS.C := TEMP_DATA(7);
|
CPU_FLAGS.Z := TEMP_DATA(6);
|
CPU_FLAGS.Z := TEMP_DATA(6);
|
CPU_FLAGS.S := TEMP_DATA(5);
|
CPU_FLAGS.S := TEMP_DATA(5);
|
CPU_FLAGS.V := TEMP_DATA(4);
|
CPU_FLAGS.V := TEMP_DATA(4);
|
CPU_FLAGS.D := TEMP_DATA(3);
|
CPU_FLAGS.D := TEMP_DATA(3);
|
CPU_FLAGS.H := TEMP_DATA(2);
|
CPU_FLAGS.H := TEMP_DATA(2);
|
CPU_FLAGS.F2 := TEMP_DATA(1);
|
CPU_FLAGS.F2 := TEMP_DATA(1);
|
CPU_FLAGS.F1 := TEMP_DATA(0);
|
CPU_FLAGS.F1 := TEMP_DATA(0);
|
SP := SP + 1;
|
SP := SP + 1;
|
MAB <= SP;
|
FRAB <= SP;
|
CPU_STATE := CPU_UNSTACK;
|
|
when CPU_UNSTACK =>
|
|
DEST_ADDR16(15 downto 8) := DATAREAD(MAB);
|
|
SP := SP + 1;
|
|
MAB <= SP;
|
|
CPU_STATE := CPU_UNSTACK2;
|
CPU_STATE := CPU_UNSTACK2;
|
when CPU_UNSTACK2 =>
|
when CPU_UNSTACK2 => -- POP PC(15:8) FROM STACK *******************************************************************************
|
DEST_ADDR16(7 downto 0) := DATAREAD(MAB);
|
DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
|
|
SP := SP + 1;
|
|
FRAB <= SP;
|
|
CPU_STATE := CPU_UNSTACK;
|
|
when CPU_UNSTACK => -- POP PC(7:0) FROM STACK ********************************************************************************
|
|
DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
|
SP := SP + 1;
|
SP := SP + 1;
|
PC := DEST_ADDR16;
|
PC := DEST_ADDR16;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
when CPU_STORE =>
|
when CPU_STORE => -- stores data into memory
|
WR <= '1';
|
WR <= '1'; -- enable write signal (it is automatically disabled on CPU_DECOD state)
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD; -- proceed to main decoding state
|
when CPU_HALTED => -- HALT mode, wait for an interrupt or reset
|
|
when CPU_ILLEGAL => -- An illegal opcode was fetched
|
when CPU_ILLEGAL => -- An illegal opcode was fetched
|
when CPU_RESET =>
|
when CPU_RESET => -- SOFTWARE RESET (TRIGGERED BY OCD RESET BIT) ***********************************************************
|
IAB <= x"0002";
|
IAB <= x"0002";
|
MAB <= x"000";
|
FRAB <= x"000";
|
PWDB <= x"00";
|
IWDB <= x"00";
|
SP := x"000";
|
SP := x"000";
|
RP := x"00";
|
RP := x"00";
|
WR <= '0';
|
WR <= '0';
|
PGM_WR <= '0';
|
PGM_WR <= '0';
|
STOP <= '0';
|
STOP <= '0';
|
Line 2131... |
Line 2151... |
CPU_STATE := CPU_VECTOR;
|
CPU_STATE := CPU_VECTOR;
|
when others =>
|
when others =>
|
CPU_STATE := CPU_DECOD;
|
CPU_STATE := CPU_DECOD;
|
end case;
|
end case;
|
-- end of the main decoder
|
-- end of the main decoder
|
end if; -- CKDIVIDER
|
|
end if;
|
end if;
|
end process;
|
end process;
|
end CPU;
|
end CPU;
|
No newline at end of file
|
No newline at end of file
|