-- 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!
|
|
|
-- Note: currently there are only a few SFRs physically implemented, they are:
|
-- Note: currently there are only a few SFRs physically implemented, they are:
|
-- 0xFC0 - IRQ0
|
-- 0xFC0 - IRQ0
|
-- 0xFC1 - IRQ0ENH
|
-- 0xFC1 - IRQ0ENH
|
-- 0xFC2 - IRQ0ENL
|
-- 0xFC2 - IRQ0ENL
|
-- 0xFCF - IRQCTL
|
-- 0xFCF - IRQCTL
|
-- 0xFD2 - PAIN
|
-- 0xFD2 - PAIN
|
-- 0xFD3 - PAOUT
|
-- 0xFD3 - PAOUT
|
-- 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/.
|
|
|
library ieee ;
|
library ieee ;
|
use ieee.std_logic_1164.all ;
|
use ieee.std_logic_1164.all ;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
use ieee.std_logic_unsigned.all ;
|
use ieee.std_logic_unsigned.all ;
|
|
|
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)
|
MEM_SEL : buffer std_logic; -- memory select
|
MEM_SEL : buffer std_logic; -- memory select
|
INT0 : in std_logic; -- interrupt 0 input (vector 0x0016)
|
INT0 : in std_logic; -- interrupt 0 input (vector 0x0016)
|
INT1 : in std_logic; -- interrupt 1 input (vector 0x0014)
|
INT1 : in std_logic; -- interrupt 1 input (vector 0x0014)
|
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
|
|
|
type Tinstqueue is array (0 TO 7) of std_logic_vector(7 downto 0);
|
type Tinstqueue is array (0 TO 7) of std_logic_vector(7 downto 0);
|
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
|
constant ALU_OR : std_logic_vector(3 downto 0):=x"4"; -- ZS V=0
|
constant ALU_OR : std_logic_vector(3 downto 0):=x"4"; -- ZS V=0
|
constant ALU_AND : std_logic_vector(3 downto 0):=x"5"; -- ZS V=0
|
constant ALU_AND : std_logic_vector(3 downto 0):=x"5"; -- ZS V=0
|
constant ALU_TCM : std_logic_vector(3 downto 0):=x"6"; -- ZS V=0
|
constant ALU_TCM : std_logic_vector(3 downto 0):=x"6"; -- ZS V=0
|
constant ALU_TM : std_logic_vector(3 downto 0):=x"7"; -- ZS V=0
|
constant ALU_TM : std_logic_vector(3 downto 0):=x"7"; -- ZS V=0
|
constant ALU_CPC : std_logic_vector(3 downto 0):=x"9"; -- CZSV
|
constant ALU_CPC : std_logic_vector(3 downto 0):=x"9"; -- CZSV
|
constant ALU_CP : std_logic_vector(3 downto 0):=x"A"; -- CZSV
|
constant ALU_CP : std_logic_vector(3 downto 0):=x"A"; -- CZSV
|
constant ALU_XOR : std_logic_vector(3 downto 0):=x"B"; -- ZS V=0
|
constant ALU_XOR : std_logic_vector(3 downto 0):=x"B"; -- ZS V=0
|
constant ALU_BSWAP : std_logic_vector(3 downto 0):=x"D"; -- ZS V=0
|
constant ALU_BSWAP : std_logic_vector(3 downto 0):=x"D"; -- ZS V=0
|
constant ALU_LD : std_logic_vector(3 downto 0):=x"E"; -- Load does not change any flag
|
constant ALU_LD : std_logic_vector(3 downto 0):=x"E"; -- Load does not change any flag
|
|
|
constant LU2_RLC : std_logic_vector(3 downto 0):=x"1"; -- CZSV
|
constant LU2_RLC : std_logic_vector(3 downto 0):=x"1"; -- CZSV
|
constant LU2_INC : std_logic_vector(3 downto 0):=x"2"; -- ZSV
|
constant LU2_INC : std_logic_vector(3 downto 0):=x"2"; -- ZSV
|
constant LU2_DEC : std_logic_vector(3 downto 0):=x"3"; -- ZSV
|
constant LU2_DEC : std_logic_vector(3 downto 0):=x"3"; -- ZSV
|
constant LU2_DA : std_logic_vector(3 downto 0):=x"4"; -- CZS
|
constant LU2_DA : std_logic_vector(3 downto 0):=x"4"; -- CZS
|
constant LU2_COM : std_logic_vector(3 downto 0):=x"6"; -- ZS V=0
|
constant LU2_COM : std_logic_vector(3 downto 0):=x"6"; -- ZS V=0
|
constant LU2_LD : std_logic_vector(3 downto 0):=x"7"; -- Load does not change any flag
|
constant LU2_LD : std_logic_vector(3 downto 0):=x"7"; -- Load does not change any flag
|
constant LU2_RL : std_logic_vector(3 downto 0):=x"9"; -- CZSV
|
constant LU2_RL : std_logic_vector(3 downto 0):=x"9"; -- CZSV
|
constant LU2_SRL : std_logic_vector(3 downto 0):=x"A"; -- CZSV
|
constant LU2_SRL : std_logic_vector(3 downto 0):=x"A"; -- CZSV
|
constant LU2_CLR : std_logic_vector(3 downto 0):=x"B"; -- Clear does not change any flag
|
constant LU2_CLR : std_logic_vector(3 downto 0):=x"B"; -- Clear does not change any flag
|
constant LU2_RRC : std_logic_vector(3 downto 0):=x"C"; -- CZSV
|
constant LU2_RRC : std_logic_vector(3 downto 0):=x"C"; -- CZSV
|
constant LU2_SRA : std_logic_vector(3 downto 0):=x"D"; -- CZSV
|
constant LU2_SRA : std_logic_vector(3 downto 0):=x"D"; -- CZSV
|
constant LU2_RR : std_logic_vector(3 downto 0):=x"E"; -- CZSV
|
constant LU2_RR : std_logic_vector(3 downto 0):=x"E"; -- CZSV
|
constant LU2_SWAP : std_logic_vector(3 downto 0):=x"F"; -- ZS
|
constant LU2_SWAP : std_logic_vector(3 downto 0):=x"F"; -- ZS
|
|
|
-- Debug commands
|
-- Debug commands
|
constant DBGCMD_READ_REV : std_logic_vector(7 downto 0):=x"00";
|
constant DBGCMD_READ_REV : std_logic_vector(7 downto 0):=x"00";
|
constant DBGCMD_READ_STATUS : std_logic_vector(7 downto 0):=x"02";
|
constant DBGCMD_READ_STATUS : std_logic_vector(7 downto 0):=x"02";
|
constant DBGCMD_READ_RUNCOUNTER : std_logic_vector(7 downto 0):=x"03";
|
constant DBGCMD_READ_RUNCOUNTER : std_logic_vector(7 downto 0):=x"03";
|
constant DBGCMD_WRITE_CTRL : std_logic_vector(7 downto 0):=x"04";
|
constant DBGCMD_WRITE_CTRL : std_logic_vector(7 downto 0):=x"04";
|
constant DBGCMD_READ_CTRL : std_logic_vector(7 downto 0):=x"05";
|
constant DBGCMD_READ_CTRL : std_logic_vector(7 downto 0):=x"05";
|
constant DBGCMD_WRITE_PC : std_logic_vector(7 downto 0):=x"06";
|
constant DBGCMD_WRITE_PC : std_logic_vector(7 downto 0):=x"06";
|
constant DBGCMD_READ_PC : std_logic_vector(7 downto 0):=x"07";
|
constant DBGCMD_READ_PC : std_logic_vector(7 downto 0):=x"07";
|
constant DBGCMD_WRITE_REG : std_logic_vector(7 downto 0):=x"08";
|
constant DBGCMD_WRITE_REG : std_logic_vector(7 downto 0):=x"08";
|
constant DBGCMD_READ_REG : std_logic_vector(7 downto 0):=x"09";
|
constant DBGCMD_READ_REG : std_logic_vector(7 downto 0):=x"09";
|
constant DBGCMD_WRITE_PROGRAM : std_logic_vector(7 downto 0):=x"0A";
|
constant DBGCMD_WRITE_PROGRAM : std_logic_vector(7 downto 0):=x"0A";
|
constant DBGCMD_READ_PROGRAM : std_logic_vector(7 downto 0):=x"0B";
|
constant DBGCMD_READ_PROGRAM : std_logic_vector(7 downto 0):=x"0B";
|
constant DBGCMD_READ_CRC : std_logic_vector(7 downto 0):=x"0E";
|
constant DBGCMD_READ_CRC : std_logic_vector(7 downto 0):=x"0E";
|
constant DBGCMD_STEP : std_logic_vector(7 downto 0):=x"10";
|
constant DBGCMD_STEP : std_logic_vector(7 downto 0):=x"10";
|
constant DBGCMD_STUFF : std_logic_vector(7 downto 0):=x"11";
|
constant DBGCMD_STUFF : std_logic_vector(7 downto 0):=x"11";
|
constant DBGCMD_EXEC : std_logic_vector(7 downto 0):=x"12";
|
constant DBGCMD_EXEC : std_logic_vector(7 downto 0):=x"12";
|
|
|
-- DATAWRITE controls where data to be written actually goes (an internal register, an external register (through register data bus) or RAM)
|
-- DATAWRITE controls where data to be written actually goes (an internal register, an external register (through register data bus) or RAM)
|
procedure DATAWRITE
|
procedure DATAWRITE
|
( ADDRESS : in std_logic_vector(11 downto 0);
|
( ADDRESS : in std_logic_vector(11 downto 0);
|
DATA : in std_logic_vector(7 downto 0)) is
|
DATA : in std_logic_vector(7 downto 0)) is
|
begin
|
begin
|
if (ADDRESS>=x"F00") then ----------------------------------------------- it is a SFR address
|
if (ADDRESS>=x"F00") then ----------------------------------------------- it is a SFR address
|
if (ADDRESS=x"FFC") then ---------------------------------------------------- FLAGS register
|
if (ADDRESS=x"FFC") then ---------------------------------------------------- FLAGS register
|
CPU_FLAGS.C := DATA(7);
|
CPU_FLAGS.C := DATA(7);
|
CPU_FLAGS.Z := DATA(6);
|
CPU_FLAGS.Z := DATA(6);
|
CPU_FLAGS.S := DATA(5);
|
CPU_FLAGS.S := DATA(5);
|
CPU_FLAGS.V := DATA(4);
|
CPU_FLAGS.V := DATA(4);
|
CPU_FLAGS.D := DATA(3);
|
CPU_FLAGS.D := DATA(3);
|
CPU_FLAGS.H := DATA(2);
|
CPU_FLAGS.H := DATA(2);
|
CPU_FLAGS.F2 := DATA(1);
|
CPU_FLAGS.F2 := DATA(1);
|
CPU_FLAGS.F1 := DATA(0);
|
CPU_FLAGS.F1 := DATA(0);
|
elsif (ADDRESS=x"FFD") then RP := DATA; ------------------------------------------- RP register
|
elsif (ADDRESS=x"FFD") then RP := DATA; ------------------------------------------- RP register
|
elsif (ADDRESS=x"FFE") then SP(11 downto 8) := DATA(3 downto 0); -------------- SPH register
|
elsif (ADDRESS=x"FFE") then SP(11 downto 8) := DATA(3 downto 0); -------------- SPH register
|
elsif (ADDRESS=x"FFF") then SP(7 downto 0) := DATA; ------------------------------ SPL register
|
elsif (ADDRESS=x"FFF") then SP(7 downto 0) := DATA; ------------------------------ SPL register
|
elsif (ADDRESS=x"FF8") then ----------------------------------------------------- FCTL register
|
elsif (ADDRESS=x"FF8") then ----------------------------------------------------- FCTL register
|
if (DATA=x"73") then FCTL:=x"01";
|
if (DATA=x"73") then FCTL:=x"01";
|
elsif (DATA=x"8C" and FCTL=x"01") then FCTL:=x"03";
|
elsif (DATA=x"8C" and FCTL=x"01") then FCTL:=x"03";
|
elsif (DATA=x"95") then FCTL:=x"04";
|
elsif (DATA=x"95") then FCTL:=x"04";
|
else FCTL:=x"00";
|
else FCTL:=x"00";
|
end if;
|
end if;
|
elsif (ADDRESS=x"FC0") then IRQ0 := DATA; --------------------------------------- IRQ0 register
|
elsif (ADDRESS=x"FC0") then IRQ0 := DATA; --------------------------------------- IRQ0 register
|
elsif (ADDRESS=x"FC1") then IRQ0ENH := DATA; ------------------------------ IRQ0ENH register
|
elsif (ADDRESS=x"FC1") then IRQ0ENH := DATA; ------------------------------ IRQ0ENH register
|
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
|
(ADDRESS : in std_logic_vector(11 downto 0))
|
(ADDRESS : in std_logic_vector(11 downto 0))
|
return std_logic_vector is
|
return std_logic_vector is
|
begin
|
begin
|
if (ADDRESS>=x"F00") then -------------------------------- it is a SFR address
|
if (ADDRESS>=x"F00") then -------------------------------- it is a SFR address
|
if (ADDRESS=x"FFC") then --------------------------------- FLAGS register
|
if (ADDRESS=x"FFC") then --------------------------------- FLAGS register
|
return (CPU_FLAGS.C,CPU_FLAGS.Z,CPU_FLAGS.S,CPU_FLAGS.V,CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.F2,CPU_FLAGS.F1);
|
return (CPU_FLAGS.C,CPU_FLAGS.Z,CPU_FLAGS.S,CPU_FLAGS.V,CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.F2,CPU_FLAGS.F1);
|
elsif (ADDRESS=x"FFD") then return RP; ------------------------ RP register
|
elsif (ADDRESS=x"FFD") then return RP; ------------------------ RP register
|
elsif (ADDRESS=x"FFE") then ----------------------------------- SPH register
|
elsif (ADDRESS=x"FFE") then ----------------------------------- SPH register
|
return "0000" & SP(11 downto 8);
|
return "0000" & SP(11 downto 8);
|
elsif (ADDRESS=x"FFF") then return SP(7 downto 0); ----------- SPL register
|
elsif (ADDRESS=x"FFF") then return SP(7 downto 0); ----------- SPL register
|
elsif (ADDRESS=x"FF8") then return FCTL; ------------------ FCTL register
|
elsif (ADDRESS=x"FF8") then return FCTL; ------------------ FCTL register
|
elsif (ADDRESS=x"FC0") then return IRQ0; ------------------ IRQ0 register
|
elsif (ADDRESS=x"FC0") then return IRQ0; ------------------ IRQ0 register
|
elsif (ADDRESS=x"FC1") then return IRQ0ENH; --------------- IRQ0ENH register
|
elsif (ADDRESS=x"FC1") then return IRQ0ENH; --------------- IRQ0ENH register
|
elsif (ADDRESS=x"FC2") then return IRQ0ENL; --------------- IRQ0ENL register
|
elsif (ADDRESS=x"FC2") then return IRQ0ENL; --------------- IRQ0ENL register
|
elsif (ADDRESS=x"FCF") then return IRQE&"0000000"; -------- IRQCTL register
|
elsif (ADDRESS=x"FCF") then return IRQE&"0000000"; -------- IRQCTL register
|
elsif (ADDRESS=x"FD2") then return PAIN; ------------------ PAIN register
|
elsif (ADDRESS=x"FD2") then return PAIN; ------------------ PAIN register
|
elsif (ADDRESS=x"FD3") then return PAOUT_BUFFER; --------- PAOUT register
|
elsif (ADDRESS=x"FD3") then return PAOUT_BUFFER; --------- PAOUT register
|
else
|
else
|
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
|
( CONDITION : in std_logic_vector(3 downto 0)) return STD_LOGIC is
|
( CONDITION : in std_logic_vector(3 downto 0)) return STD_LOGIC is
|
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
|
( ADDR : in std_logic_vector(11 downto 0)) return std_logic_vector is
|
( ADDR : in std_logic_vector(11 downto 0)) return std_logic_vector is
|
begin
|
begin
|
if (ADDR(11 downto 4)=x"EE") then -- escaped addressing mode (work register)
|
if (ADDR(11 downto 4)=x"EE") then -- escaped addressing mode (work register)
|
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);
|
elsif (ADDR(11 downto 8)=x"E") then -- escaped addressing mode (register)
|
elsif (ADDR(11 downto 8)=x"E") then -- escaped addressing mode (register)
|
return RP(3 downto 0) & ADDR(7 downto 0);
|
return RP(3 downto 0) & ADDR(7 downto 0);
|
else return ADDR; -- full address
|
else return ADDR; -- full address
|
end if;
|
end if;
|
end ADDRESSER12;
|
end ADDRESSER12;
|
|
|
-- ADDRESSER8 generates a 12-bit address from an 8-bit address (it decides when to use escaped addressing mode)
|
-- ADDRESSER8 generates a 12-bit address from an 8-bit address (it decides when to use escaped addressing mode)
|
function ADDRESSER8
|
function ADDRESSER8
|
( ADDR : in std_logic_vector(7 downto 0)) return std_logic_vector is
|
( ADDR : in std_logic_vector(7 downto 0)) return std_logic_vector is
|
begin
|
begin
|
if (ADDR(7 downto 4)=x"E") then -- escaped addressing mode (register)
|
if (ADDR(7 downto 4)=x"E") then -- escaped addressing mode (register)
|
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;
|
|
|
-- ALU is the arithmetic and logic unit, it receives two 8-bit operands along with a 4-bit operation code and a carry input, returning an 8-bit result
|
-- ALU is the arithmetic and logic unit, it receives two 8-bit operands along with a 4-bit operation code and a carry input, returning an 8-bit result
|
function ALU
|
function ALU
|
( ALU_OP : in std_logic_vector(3 downto 0);
|
( ALU_OP : in std_logic_vector(3 downto 0);
|
OPER1 : in std_logic_vector(7 downto 0);
|
OPER1 : in std_logic_vector(7 downto 0);
|
OPER2 : in std_logic_vector(7 downto 0);
|
OPER2 : in std_logic_vector(7 downto 0);
|
CIN : in STD_LOGIC) return std_logic_vector is
|
CIN : in STD_LOGIC) return std_logic_vector is
|
variable RESULT : std_logic_vector(7 downto 0);
|
variable RESULT : std_logic_vector(7 downto 0);
|
variable HALF1,HALF2 : std_logic_vector(4 downto 0);
|
variable HALF1,HALF2 : std_logic_vector(4 downto 0);
|
begin
|
begin
|
ALU_NOUPDATE := '0';
|
ALU_NOUPDATE := '0';
|
case ALU_OP is
|
case ALU_OP is
|
when ALU_ADD => -- ADD operation **************************************************
|
when ALU_ADD => -- ADD operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0));
|
HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0));
|
ALU_FLAGS.H := HALF1(4);
|
ALU_FLAGS.H := HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := HALF2(4);
|
ALU_FLAGS.C := HALF2(4);
|
if (OPER1(7)=OPER2(7)) then
|
if (OPER1(7)=OPER2(7)) then
|
if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
when ALU_ADC => -- ADC operation **************************************************
|
when ALU_ADC => -- ADC operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0)+(CIN));
|
HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0)+(CIN));
|
ALU_FLAGS.H := HALF1(4);
|
ALU_FLAGS.H := HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := HALF2(4);
|
ALU_FLAGS.C := HALF2(4);
|
if (OPER1(7)=OPER2(7)) then
|
if (OPER1(7)=OPER2(7)) then
|
if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
when ALU_SUB => -- SUB operation **************************************************
|
when ALU_SUB => -- SUB operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
|
ALU_FLAGS.H := (HALF1(4));
|
ALU_FLAGS.H := (HALF1(4));
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := (HALF2(4));
|
ALU_FLAGS.C := (HALF2(4));
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
when ALU_SBC => -- SBC operation **************************************************
|
when ALU_SBC => -- SBC operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
|
ALU_FLAGS.H := (HALF1(4));
|
ALU_FLAGS.H := (HALF1(4));
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := (HALF2(4));
|
ALU_FLAGS.C := (HALF2(4));
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
when ALU_OR => -- Logical or operation ***********************************************
|
when ALU_OR => -- Logical or operation ***********************************************
|
RESULT := OPER1 or OPER2;
|
RESULT := OPER1 or OPER2;
|
when ALU_AND => -- Logical AND operation **********************************************
|
when ALU_AND => -- Logical AND operation **********************************************
|
RESULT := OPER1 AND OPER2;
|
RESULT := OPER1 AND OPER2;
|
when ALU_TCM => -- Test Complement Mask operation *************************************
|
when ALU_TCM => -- Test Complement Mask operation *************************************
|
RESULT := (NOT OPER1) AND OPER2;
|
RESULT := (NOT OPER1) AND OPER2;
|
ALU_NOUPDATE := '1';
|
ALU_NOUPDATE := '1';
|
when ALU_TM => -- Test Mask operation ************************************************
|
when ALU_TM => -- Test Mask operation ************************************************
|
RESULT := OPER1 AND OPER2;
|
RESULT := OPER1 AND OPER2;
|
ALU_NOUPDATE := '1';
|
ALU_NOUPDATE := '1';
|
when ALU_CPC => -- CPC operation **************************************************
|
when ALU_CPC => -- CPC operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
|
ALU_FLAGS.H := (HALF1(4));
|
ALU_FLAGS.H := (HALF1(4));
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := (HALF2(4));
|
ALU_FLAGS.C := (HALF2(4));
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
ALU_NOUPDATE := '1';
|
ALU_NOUPDATE := '1';
|
when ALU_CP => -- Compare operation **************************************************
|
when ALU_CP => -- Compare operation **************************************************
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
|
HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
|
ALU_FLAGS.H := (HALF1(4));
|
ALU_FLAGS.H := (HALF1(4));
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
|
ALU_FLAGS.C := (HALF2(4));
|
ALU_FLAGS.C := (HALF2(4));
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)/=OPER2(7)) then
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
else ALU_FLAGS.V:='0';
|
else ALU_FLAGS.V:='0';
|
end if;
|
end if;
|
ALU_NOUPDATE := '1';
|
ALU_NOUPDATE := '1';
|
when ALU_XOR => -- Logical xor operation **********************************************
|
when ALU_XOR => -- Logical xor operation **********************************************
|
RESULT := OPER1 xor OPER2;
|
RESULT := OPER1 xor OPER2;
|
when ALU_BSWAP => -- Bit Swap operation *********************************************
|
when ALU_BSWAP => -- Bit Swap operation *********************************************
|
RESULT := OPER2(0)&OPER2(1)&OPER2(2)&OPER2(3)&OPER2(4)&OPER2(5)&OPER2(6)&OPER2(7);
|
RESULT := OPER2(0)&OPER2(1)&OPER2(2)&OPER2(3)&OPER2(4)&OPER2(5)&OPER2(6)&OPER2(7);
|
when others => -- Load operation *****************************************************
|
when others => -- Load operation *****************************************************
|
RESULT := OPER2;
|
RESULT := OPER2;
|
|
|
end case;
|
end case;
|
if (RESULT(7 downto 0)=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
|
if (RESULT(7 downto 0)=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
|
end if;
|
end if;
|
ALU_FLAGS.S := RESULT(7);
|
ALU_FLAGS.S := RESULT(7);
|
return RESULT(7 downto 0);
|
return RESULT(7 downto 0);
|
end ALU;
|
end ALU;
|
|
|
-- LU2 is the second logic unit, it performs mostly logical operations not covered by the ALU
|
-- LU2 is the second logic unit, it performs mostly logical operations not covered by the ALU
|
function LU2
|
function LU2
|
( LU2_OP : in std_logic_vector(3 downto 0);
|
( LU2_OP : in std_logic_vector(3 downto 0);
|
OPER : in std_logic_vector(7 downto 0);
|
OPER : in std_logic_vector(7 downto 0);
|
DIN : in std_logic;
|
DIN : in std_logic;
|
HIN : in std_logic;
|
HIN : in std_logic;
|
CIN : in std_logic) return std_logic_vector is
|
CIN : in std_logic) return std_logic_vector is
|
variable RESULT : std_logic_vector(7 downto 0);
|
variable RESULT : std_logic_vector(7 downto 0);
|
begin
|
begin
|
case LU2_OP is
|
case LU2_OP is
|
when LU2_RLC => -- RLC operation **************************************************
|
when LU2_RLC => -- RLC operation **************************************************
|
ALU_FLAGS.C := OPER(7);
|
ALU_FLAGS.C := OPER(7);
|
RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&CIN;
|
RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&CIN;
|
when LU2_INC => -- INC operation **************************************************
|
when LU2_INC => -- INC operation **************************************************
|
RESULT := OPER+1;
|
RESULT := OPER+1;
|
if (RESULT=x"00") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
|
if (RESULT=x"00") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
|
end if;
|
end if;
|
when LU2_DEC => -- DEC operation **************************************************
|
when LU2_DEC => -- DEC operation **************************************************
|
RESULT := OPER-1;
|
RESULT := OPER-1;
|
if (RESULT=x"FF") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
|
if (RESULT=x"FF") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
|
end if;
|
end if;
|
when LU2_DA => -- DA operation ***************************************************
|
when LU2_DA => -- DA operation ***************************************************
|
if (DIN='0') then -- decimal adjust following an add operation
|
if (DIN='0') then -- decimal adjust following an add operation
|
if (OPER(3 downto 0)>x"9" or HIN='1') then
|
if (OPER(3 downto 0)>x"9" or HIN='1') then
|
RESULT := ALU(ALU_ADD,OPER,x"06",'0');
|
RESULT := ALU(ALU_ADD,OPER,x"06",'0');
|
else RESULT := OPER;
|
else RESULT := OPER;
|
end if;
|
end if;
|
if (RESULT(7 downto 4)>x"9" or ALU_FLAGS.C='1') then
|
if (RESULT(7 downto 4)>x"9" or ALU_FLAGS.C='1') then
|
RESULT := ALU(ALU_ADD,RESULT,x"60",'0');
|
RESULT := ALU(ALU_ADD,RESULT,x"60",'0');
|
end if;
|
end if;
|
else -------------- decimal adjust following a sub operation
|
else -------------- decimal adjust following a sub operation
|
end if;
|
end if;
|
when LU2_COM => -- COM operation **************************************************
|
when LU2_COM => -- COM operation **************************************************
|
RESULT := NOT OPER;
|
RESULT := NOT OPER;
|
when LU2_RL => -- RL operation ***************************************************
|
when LU2_RL => -- RL operation ***************************************************
|
ALU_FLAGS.C := OPER(7);
|
ALU_FLAGS.C := OPER(7);
|
RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&ALU_FLAGS.C;
|
RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&ALU_FLAGS.C;
|
when LU2_SRL => -- SRL operation **************************************************
|
when LU2_SRL => -- SRL operation **************************************************
|
ALU_FLAGS.C := OPER(0);
|
ALU_FLAGS.C := OPER(0);
|
RESULT := '0'&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
RESULT := '0'&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
when LU2_RRC => -- RRC operation **************************************************
|
when LU2_RRC => -- RRC operation **************************************************
|
ALU_FLAGS.C := OPER(0);
|
ALU_FLAGS.C := OPER(0);
|
RESULT := CIN&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
RESULT := CIN&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
when LU2_RR => -- RR operation ***************************************************
|
when LU2_RR => -- RR operation ***************************************************
|
ALU_FLAGS.C := OPER(0);
|
ALU_FLAGS.C := OPER(0);
|
RESULT := ALU_FLAGS.C&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
RESULT := ALU_FLAGS.C&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
when LU2_SRA => -- SRA operation **************************************************
|
when LU2_SRA => -- SRA operation **************************************************
|
ALU_FLAGS.C := OPER(0);
|
ALU_FLAGS.C := OPER(0);
|
RESULT := OPER(7)&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
RESULT := OPER(7)&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
|
when LU2_SWAP => -- SWAP operation *************************************************
|
when LU2_SWAP => -- SWAP operation *************************************************
|
RESULT := OPER(3)&OPER(2)&OPER(1)&OPER(0)&OPER(7)&OPER(6)&OPER(5)&OPER(4);
|
RESULT := OPER(3)&OPER(2)&OPER(1)&OPER(0)&OPER(7)&OPER(6)&OPER(5)&OPER(4);
|
when LU2_LD => -- LOAD operation *************************************************
|
when LU2_LD => -- LOAD operation *************************************************
|
RESULT := OPER;
|
RESULT := OPER;
|
when others => -- CLR operation **************************************************
|
when others => -- CLR operation **************************************************
|
RESULT := x"00";
|
RESULT := x"00";
|
end case;
|
end case;
|
if (OPER(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
if (OPER(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
|
end if;
|
end if;
|
if (RESULT=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
|
if (RESULT=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
|
end if;
|
end if;
|
ALU_FLAGS.S := RESULT(7);
|
ALU_FLAGS.S := RESULT(7);
|
return RESULT;
|
return RESULT;
|
end LU2;
|
end LU2;
|
|
|
-- ADDER16 adds a signed 8-bit offset to a 16-bit address
|
-- ADDER16 adds a signed 8-bit offset to a 16-bit address
|
function ADDER16
|
function ADDER16
|
( ADDR16 : in std_logic_vector(15 downto 0);
|
( ADDR16 : in std_logic_vector(15 downto 0);
|
OFFSET : in std_logic_vector(7 downto 0)) return std_logic_vector is
|
OFFSET : in std_logic_vector(7 downto 0)) return std_logic_vector is
|
begin
|
begin
|
if (OFFSET(7)='0') then return ADDR16 + (x"00" & OFFSET);
|
if (OFFSET(7)='0') then return ADDR16 + (x"00" & OFFSET);
|
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
|
);
|
);
|
type Tdbg_uartrxstate is (
|
type Tdbg_uartrxstate is (
|
DBGST_NOSYNC, -- debug UART receiver is not synchronized to the host
|
DBGST_NOSYNC, -- debug UART receiver is not synchronized to the host
|
DBGST_WAITSTART, -- debug UART receiver is waiting for a 0x80 char
|
DBGST_WAITSTART, -- debug UART receiver is waiting for a 0x80 char
|
DBGST_MEASURING, -- debug UART receiver is measuring a possible sync char
|
DBGST_MEASURING, -- debug UART receiver is measuring a possible sync char
|
DBGST_IDLE, -- debug UART receiver is synchronized and awaiting commands
|
DBGST_IDLE, -- debug UART receiver is synchronized and awaiting commands
|
DBGST_START, -- debug UART received a start bit
|
DBGST_START, -- debug UART received a start bit
|
DBGST_RECEIVING, -- debug UART is receiving new command/data
|
DBGST_RECEIVING, -- debug UART is receiving new command/data
|
DBGST_ERROR -- debug UART receiver is in error state
|
DBGST_ERROR -- debug UART receiver is in error state
|
);
|
);
|
type Tdbg_uarttxstate is (
|
type Tdbg_uarttxstate is (
|
DBGTX_INIT, -- debug UART transmitter is initializing
|
DBGTX_INIT, -- debug UART transmitter is initializing
|
DBGTX_IDLE, -- debug UART transmitter is waiting new data to transmit
|
DBGTX_IDLE, -- debug UART transmitter is waiting new data to transmit
|
DBGTX_START, -- debug UART transmitter is sending a start bit
|
DBGTX_START, -- debug UART transmitter is sending a start bit
|
DBGTX_TRASMITTING, -- debug UART transmitter is sending data
|
DBGTX_TRASMITTING, -- debug UART transmitter is sending data
|
DBGTX_BREAK, -- debug UART transmitter is preparing to send a break
|
DBGTX_BREAK, -- debug UART transmitter is preparing to send a break
|
DBGTX_BREAK2 -- debug UART is waiting for the break complete
|
DBGTX_BREAK2 -- debug UART is waiting for the break complete
|
);
|
);
|
type Tdbg_command is (
|
type Tdbg_command is (
|
DBG_WAIT_CMD, -- debugger is waiting for commands
|
DBG_WAIT_CMD, -- debugger is waiting for commands
|
DBG_SEND_REV, DBG_SEND_REV2, -- debugger is processing a read revision command
|
DBG_SEND_REV, DBG_SEND_REV2, -- debugger is processing a read revision command
|
DBG_SEND_STATUS, -- debugger is processing a read OCDST command
|
DBG_SEND_STATUS, -- debugger is processing a read OCDST command
|
DBG_WRITE_CTRL, -- debugger is processing a write OCDCTRL command
|
DBG_WRITE_CTRL, -- debugger is processing a write OCDCTRL command
|
DBG_SEND_CTRL, -- debugger is processing a read OCDCTRL command
|
DBG_SEND_CTRL, -- debugger is processing a read OCDCTRL command
|
DBG_WRITE_PC, DBG_WRITE_PC2, -- debugger is processing a PC write command
|
DBG_WRITE_PC, DBG_WRITE_PC2, -- debugger is processing a PC write command
|
DBG_SEND_PC, DBG_SEND_PC2, -- debugger is processing a PC read command
|
DBG_SEND_PC, DBG_SEND_PC2, -- debugger is processing a PC read command
|
DBG_WRITE_REG, DBG_READ_REG, -- debugger is processing a read/write to registers
|
DBG_WRITE_REG, DBG_READ_REG, -- debugger is processing a read/write to registers
|
DBG_REG, DBG_REG2, DBG_REG3, -- debugger is processing a read/write to registers
|
DBG_REG, DBG_REG2, DBG_REG3, -- debugger is processing a read/write to registers
|
DBG_REG4, DBG_REG5, -- debugger is processing a read/write to registers
|
DBG_REG4, DBG_REG5, -- debugger is processing a read/write to registers
|
DBG_WRITE_PROGMEM, DBG_READ_PROGMEM, -- debugger is processing a read/write to program memory
|
DBG_WRITE_PROGMEM, DBG_READ_PROGMEM, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM, DBG_PROGMEM2, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM, DBG_PROGMEM2, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM3, DBG_PROGMEM4, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM3, DBG_PROGMEM4, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM5, DBG_PROGMEM6, -- debugger is processing a read/write to program memory
|
DBG_PROGMEM5, DBG_PROGMEM6, -- debugger is processing a read/write to program memory
|
DBG_STEP, -- debugger is processing a step command
|
DBG_STEP, -- debugger is processing a step command
|
DBG_STUFF, -- debugger is processing a stuff command
|
DBG_STUFF, -- debugger is processing a stuff command
|
DBG_EXEC, DBG_EXEC2, DBG_EXEC3 -- debugger is processing a execute command
|
DBG_EXEC, DBG_EXEC2, DBG_EXEC3 -- debugger is processing a execute command
|
);
|
);
|
type Tdbg_uart is record
|
type Tdbg_uart is record
|
RX_STATE : Tdbg_uartrxstate;
|
RX_STATE : Tdbg_uartrxstate;
|
TX_STATE : Tdbg_uarttxstate;
|
TX_STATE : Tdbg_uarttxstate;
|
RX_DONE : std_logic; -- new data is available
|
RX_DONE : std_logic; -- new data is available
|
TX_EMPTY : std_logic; -- tx buffer is empty
|
TX_EMPTY : std_logic; -- tx buffer is empty
|
DBG_SYNC : std_logic; -- debugger is synchronized to host
|
DBG_SYNC : std_logic; -- debugger is synchronized to host
|
WRT : std_logic; -- write/read command flag
|
WRT : std_logic; -- write/read command flag
|
LAST_SMP : std_logic; -- last sample read from DBG_RX pin
|
LAST_SMP : std_logic; -- last sample read from DBG_RX pin
|
SIZE : std_logic_vector(15 downto 0); -- 16-bit size of command
|
SIZE : std_logic_vector(15 downto 0); -- 16-bit size of command
|
TXSHIFTREG : std_logic_vector(8 downto 0); -- transmitter shift register
|
TXSHIFTREG : std_logic_vector(8 downto 0); -- transmitter shift register
|
RXSHIFTREG : std_logic_vector(8 downto 0); -- receiver shift register
|
RXSHIFTREG : std_logic_vector(8 downto 0); -- receiver shift register
|
TX_DATA : std_logic_vector(7 downto 0); -- TX buffer
|
TX_DATA : std_logic_vector(7 downto 0); -- TX buffer
|
RX_DATA : std_logic_vector(7 downto 0); -- RX buffer
|
RX_DATA : std_logic_vector(7 downto 0); -- RX buffer
|
RXCNT : integer range 0 to 15; -- received bit counter
|
RXCNT : integer range 0 to 15; -- received bit counter
|
TXCNT : integer range 0 to 15; -- transmitted bit counter
|
TXCNT : integer range 0 to 15; -- transmitted bit counter
|
BAUDPRE : integer range 0 to 2; -- baud prescaler
|
BAUDPRE : integer range 0 to 2; -- baud prescaler
|
BAUDCNTRX : std_logic_vector(11 downto 0); -- RX baud divider
|
BAUDCNTRX : std_logic_vector(11 downto 0); -- RX baud divider
|
BAUDCNTTX : std_logic_vector(11 downto 0); -- TX baud divider
|
BAUDCNTTX : std_logic_vector(11 downto 0); -- TX baud divider
|
BITTIMERX : std_logic_vector(11 downto 0); -- RX bit-time register (1/2 bit-time)
|
BITTIMERX : std_logic_vector(11 downto 0); -- RX bit-time register (1/2 bit-time)
|
BITTIMETX : std_logic_vector(11 downto 0); -- TX bit-time register
|
BITTIMETX : std_logic_vector(11 downto 0); -- TX bit-time register
|
end record;
|
end record;
|
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;
|
QUEUE : Tinstqueue;
|
QUEUE : Tinstqueue;
|
FULL : std_logic; -- indicates whether the queue is full or not
|
FULL : std_logic; -- indicates whether the queue is full or not
|
end record;
|
end record;
|
variable IQUEUE : Tinstructionqueue;
|
variable IQUEUE : Tinstructionqueue;
|
type Tocdcr is record
|
type Tocdcr is record
|
DBGMODE : std_logic;
|
DBGMODE : std_logic;
|
BRKEN : std_logic;
|
BRKEN : std_logic;
|
DBGACK : std_logic;
|
DBGACK : std_logic;
|
BRKLOOP : std_logic;
|
BRKLOOP : std_logic;
|
RST : std_logic;
|
RST : std_logic;
|
end record;
|
end record;
|
variable OCDCR : Tocdcr;
|
variable OCDCR : Tocdcr;
|
type Tocdflags is record
|
type Tocdflags is record
|
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';
|
CAN_FETCH := '1';
|
CAN_FETCH := '1';
|
FETCH_ADDR := x"0000";
|
FETCH_ADDR := x"0000";
|
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
DBG_UART.TX_STATE := DBGTX_INIT;
|
DBG_UART.TX_STATE := DBGTX_INIT;
|
OCDCR.DBGMODE := '0';
|
OCDCR.DBGMODE := '0';
|
OCDCR.BRKEN := '0';
|
OCDCR.BRKEN := '0';
|
OCDCR.DBGACK := '0';
|
OCDCR.DBGACK := '0';
|
OCDCR.BRKLOOP := '0';
|
OCDCR.BRKLOOP := '0';
|
OCD.SINGLESTEP := '0';
|
OCD.SINGLESTEP := '0';
|
OCDCR.RST := '0';
|
OCDCR.RST := '0';
|
RXSYNC1 <= '1';
|
RXSYNC1 <= '1';
|
RXSYNC2 <= '1';
|
RXSYNC2 <= '1';
|
DBG_UART.LAST_SMP := '1';
|
DBG_UART.LAST_SMP := '1';
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IRQE := '0';
|
IRQE := '0';
|
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;
|
IQUEUE.RDPOS := 0;
|
IQUEUE.RDPOS := 0;
|
IQUEUE.CNT := 0;
|
IQUEUE.CNT := 0;
|
IQUEUE.FETCH_STATE := F_READ;
|
IQUEUE.FETCH_STATE := F_READ;
|
else
|
else
|
if (IQUEUE.FULL='0') then
|
if (IQUEUE.FULL='0') then
|
IQUEUE.QUEUE(IQUEUE.WRPOS) := IDB;
|
IQUEUE.QUEUE(IQUEUE.WRPOS) := IDB;
|
FETCH_ADDR := FETCH_ADDR + 1;
|
FETCH_ADDR := FETCH_ADDR + 1;
|
IAB <= FETCH_ADDR;
|
IAB <= FETCH_ADDR;
|
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
|
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
|
IQUEUE.CNT := IQUEUE.CNT + 1;
|
IQUEUE.CNT := IQUEUE.CNT + 1;
|
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;
|
DBG_UART.RX_STATE := DBGST_WAITSTART;
|
DBG_UART.RX_STATE := DBGST_WAITSTART;
|
when DBGST_WAITSTART =>
|
when DBGST_WAITSTART =>
|
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then
|
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then
|
DBG_UART.RX_STATE := DBGST_MEASURING;
|
DBG_UART.RX_STATE := DBGST_MEASURING;
|
DBG_UART.BAUDCNTRX := x"000";
|
DBG_UART.BAUDCNTRX := x"000";
|
end if;
|
end if;
|
when DBGST_MEASURING =>
|
when DBGST_MEASURING =>
|
if (DBG_UART.BAUDCNTRX/=x"FFF") then
|
if (DBG_UART.BAUDCNTRX/=x"FFF") then
|
if (RXSYNC1='1') then
|
if (RXSYNC1='1') then
|
DBG_UART.DBG_SYNC := '1';
|
DBG_UART.DBG_SYNC := '1';
|
DBG_UART.RX_STATE := DBGST_IDLE;
|
DBG_UART.RX_STATE := DBGST_IDLE;
|
DBG_UART.BITTIMERX := "0000"&DBG_UART.BAUDCNTRX(11 downto 4);
|
DBG_UART.BITTIMERX := "0000"&DBG_UART.BAUDCNTRX(11 downto 4);
|
DBG_UART.BITTIMETX := "000"&DBG_UART.BAUDCNTRX(11 downto 3);
|
DBG_UART.BITTIMETX := "000"&DBG_UART.BAUDCNTRX(11 downto 3);
|
end if;
|
end if;
|
else
|
else
|
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
DBG_UART.RX_STATE := DBGST_NOSYNC;
|
end if;
|
end if;
|
when DBGST_IDLE =>
|
when DBGST_IDLE =>
|
DBG_UART.BAUDCNTRX:=x"000";
|
DBG_UART.BAUDCNTRX:=x"000";
|
DBG_UART.RXCNT:=0;
|
DBG_UART.RXCNT:=0;
|
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then -- it's a start bit
|
if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then -- it's a start bit
|
DBG_UART.RX_STATE := DBGST_START;
|
DBG_UART.RX_STATE := DBGST_START;
|
end if;
|
end if;
|
when DBGST_START =>
|
when DBGST_START =>
|
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMERX) then
|
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMERX) then
|
DBG_UART.BAUDCNTRX:=x"000";
|
DBG_UART.BAUDCNTRX:=x"000";
|
if (RXSYNC1='0') then
|
if (RXSYNC1='0') then
|
DBG_UART.RX_STATE := DBGST_RECEIVING;
|
DBG_UART.RX_STATE := DBGST_RECEIVING;
|
else
|
else
|
DBG_UART.RX_STATE := DBGST_ERROR;
|
DBG_UART.RX_STATE := DBGST_ERROR;
|
DBG_UART.TX_STATE := DBGTX_BREAK;
|
DBG_UART.TX_STATE := DBGTX_BREAK;
|
end if;
|
end if;
|
end if;
|
end if;
|
when DBGST_RECEIVING =>
|
when DBGST_RECEIVING =>
|
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMETX) then
|
if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMETX) then
|
DBG_UART.BAUDCNTRX:=x"000";
|
DBG_UART.BAUDCNTRX:=x"000";
|
-- one bit time elapsed, sample RX input
|
-- one bit time elapsed, sample RX input
|
DBG_UART.RXSHIFTREG := RXSYNC1 & DBG_UART.RXSHIFTREG(8 downto 1);
|
DBG_UART.RXSHIFTREG := RXSYNC1 & DBG_UART.RXSHIFTREG(8 downto 1);
|
DBG_UART.RXCNT := DBG_UART.RXCNT + 1;
|
DBG_UART.RXCNT := DBG_UART.RXCNT + 1;
|
if (DBG_UART.RXCNT=9) then
|
if (DBG_UART.RXCNT=9) then
|
if (RXSYNC1='1') then
|
if (RXSYNC1='1') then
|
-- if the stop bit is 1, rx is completed ok
|
-- if the stop bit is 1, rx is completed ok
|
DBG_UART.RX_DATA := DBG_UART.RXSHIFTREG(7 downto 0);
|
DBG_UART.RX_DATA := DBG_UART.RXSHIFTREG(7 downto 0);
|
DBG_UART.RX_DONE := '1';
|
DBG_UART.RX_DONE := '1';
|
DBG_UART.RX_STATE := DBGST_IDLE;
|
DBG_UART.RX_STATE := DBGST_IDLE;
|
else
|
else
|
-- if the stop bit is 0, it is a break char, reset receiver
|
-- if the stop bit is 0, it is a break char, reset receiver
|
DBG_UART.RX_STATE := DBGST_ERROR;
|
DBG_UART.RX_STATE := DBGST_ERROR;
|
DBG_UART.TX_STATE := DBGTX_BREAK;
|
DBG_UART.TX_STATE := DBGTX_BREAK;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
when others =>
|
when others =>
|
end case;
|
end case;
|
DBG_UART.LAST_SMP := RXSYNC1;
|
DBG_UART.LAST_SMP := RXSYNC1;
|
case DBG_UART.TX_STATE is
|
case DBG_UART.TX_STATE is
|
when DBGTX_INIT =>
|
when DBGTX_INIT =>
|
DBG_UART.TX_EMPTY := '1';
|
DBG_UART.TX_EMPTY := '1';
|
DBG_UART.TX_STATE:=DBGTX_IDLE;
|
DBG_UART.TX_STATE:=DBGTX_IDLE;
|
when DBGTX_IDLE => -- UART is idle and not transmitting
|
when DBGTX_IDLE => -- UART is idle and not transmitting
|
DBG_TX <= '1';
|
DBG_TX <= '1';
|
if (DBG_UART.TX_EMPTY='0' and DBG_UART.DBG_SYNC='1') then -- there is new data in TX_DATA register
|
if (DBG_UART.TX_EMPTY='0' and DBG_UART.DBG_SYNC='1') then -- there is new data in TX_DATA register
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.TX_STATE := DBGTX_START;
|
DBG_UART.TX_STATE := DBGTX_START;
|
end if;
|
end if;
|
when DBGTX_START =>
|
when DBGTX_START =>
|
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
|
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TX_DATA;
|
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TX_DATA;
|
DBG_UART.TXCNT := 10;
|
DBG_UART.TXCNT := 10;
|
DBG_UART.TX_STATE := DBGTX_TRASMITTING;
|
DBG_UART.TX_STATE := DBGTX_TRASMITTING;
|
DBG_TX <= '0';
|
DBG_TX <= '0';
|
end if;
|
end if;
|
when DBGTX_TRASMITTING => -- UART is shifting data
|
when DBGTX_TRASMITTING => -- UART is shifting data
|
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
|
if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_TX <= DBG_UART.TXSHIFTREG(0);
|
DBG_TX <= DBG_UART.TXSHIFTREG(0);
|
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TXSHIFTREG(8 downto 1);
|
DBG_UART.TXSHIFTREG := '1'&DBG_UART.TXSHIFTREG(8 downto 1);
|
DBG_UART.TXCNT :=DBG_UART.TXCNT - 1;
|
DBG_UART.TXCNT :=DBG_UART.TXCNT - 1;
|
if (DBG_UART.TXCNT=0) then
|
if (DBG_UART.TXCNT=0) then
|
DBG_UART.TX_STATE:=DBGTX_IDLE;
|
DBG_UART.TX_STATE:=DBGTX_IDLE;
|
DBG_UART.TX_EMPTY := '1';
|
DBG_UART.TX_EMPTY := '1';
|
end if;
|
end if;
|
end if;
|
end if;
|
when DBGTX_BREAK =>
|
when DBGTX_BREAK =>
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.BAUDCNTTX:=x"000";
|
DBG_UART.TX_STATE:=DBGTX_BREAK2;
|
DBG_UART.TX_STATE:=DBGTX_BREAK2;
|
when DBGTX_BREAK2 =>
|
when DBGTX_BREAK2 =>
|
DBG_TX <= '0';
|
DBG_TX <= '0';
|
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;
|
when DBGCMD_READ_STATUS => DBG_CMD := DBG_SEND_STATUS;
|
when DBGCMD_READ_STATUS => DBG_CMD := DBG_SEND_STATUS;
|
when DBGCMD_WRITE_CTRL => DBG_CMD := DBG_WRITE_CTRL;
|
when DBGCMD_WRITE_CTRL => DBG_CMD := DBG_WRITE_CTRL;
|
when DBGCMD_READ_CTRL => DBG_CMD := DBG_SEND_CTRL;
|
when DBGCMD_READ_CTRL => DBG_CMD := DBG_SEND_CTRL;
|
when DBGCMD_WRITE_PC => DBG_CMD := DBG_WRITE_PC;
|
when DBGCMD_WRITE_PC => DBG_CMD := DBG_WRITE_PC;
|
when DBGCMD_READ_PC => DBG_CMD := DBG_SEND_PC;
|
when DBGCMD_READ_PC => DBG_CMD := DBG_SEND_PC;
|
when DBGCMD_WRITE_REG => DBG_CMD := DBG_WRITE_REG;
|
when DBGCMD_WRITE_REG => DBG_CMD := DBG_WRITE_REG;
|
when DBGCMD_READ_REG => DBG_CMD := DBG_READ_REG;
|
when DBGCMD_READ_REG => DBG_CMD := DBG_READ_REG;
|
when DBGCMD_WRITE_PROGRAM=> DBG_CMD := DBG_WRITE_PROGMEM;
|
when DBGCMD_WRITE_PROGRAM=> DBG_CMD := DBG_WRITE_PROGMEM;
|
when DBGCMD_READ_PROGRAM=> DBG_CMD := DBG_READ_PROGMEM;
|
when DBGCMD_READ_PROGRAM=> DBG_CMD := DBG_READ_PROGMEM;
|
when DBGCMD_STEP => DBG_CMD := DBG_STEP;
|
when DBGCMD_STEP => DBG_CMD := DBG_STEP;
|
when DBGCMD_STUFF => DBG_CMD := DBG_STUFF;
|
when DBGCMD_STUFF => DBG_CMD := DBG_STUFF;
|
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);
|
OCDCR.BRKLOOP := DBG_UART.RX_DATA(4);
|
OCDCR.BRKLOOP := DBG_UART.RX_DATA(4);
|
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';
|
DBG_CMD := DBG_PROGMEM;
|
DBG_CMD := DBG_PROGMEM;
|
when DBG_PROGMEM =>
|
when DBG_PROGMEM =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
CAN_FETCH := '0';
|
CAN_FETCH := '0';
|
IAB(15 downto 8) <= DBG_UART.RX_DATA;
|
IAB(15 downto 8) <= DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_PROGMEM2;
|
DBG_CMD := DBG_PROGMEM2;
|
end if;
|
end if;
|
when DBG_PROGMEM2 =>
|
when DBG_PROGMEM2 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
IAB(7 downto 0) <= DBG_UART.RX_DATA;
|
IAB(7 downto 0) <= DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_PROGMEM3;
|
DBG_CMD := DBG_PROGMEM3;
|
end if;
|
end if;
|
when DBG_PROGMEM3 =>
|
when DBG_PROGMEM3 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
DBG_UART.SIZE(15 downto 8) := DBG_UART.RX_DATA;
|
DBG_UART.SIZE(15 downto 8) := DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_PROGMEM4;
|
DBG_CMD := DBG_PROGMEM4;
|
end if;
|
end if;
|
when DBG_PROGMEM4 =>
|
when DBG_PROGMEM4 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
DBG_UART.SIZE(7 downto 0) := DBG_UART.RX_DATA;
|
DBG_UART.SIZE(7 downto 0) := DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
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
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=IDB;
|
DBG_UART.TX_DATA:=IDB;
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
DBG_CMD := DBG_PROGMEM6;
|
DBG_CMD := DBG_PROGMEM6;
|
end if;
|
end if;
|
end if;
|
end if;
|
when DBG_PROGMEM6 =>
|
when DBG_PROGMEM6 =>
|
IAB <= IAB + 1;
|
IAB <= IAB + 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';
|
CAN_FETCH := '1';
|
IQUEUE.CNT := 0;
|
IQUEUE.CNT := 0;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
else DBG_CMD := DBG_PROGMEM5;
|
else DBG_CMD := DBG_PROGMEM5;
|
end if;
|
end if;
|
when DBG_STEP =>
|
when DBG_STEP =>
|
OCD.SINGLESTEP:='1';
|
OCD.SINGLESTEP:='1';
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
DBG_CMD := DBG_WAIT_CMD;
|
DBG_CMD := DBG_WAIT_CMD;
|
when DBG_STUFF =>
|
when DBG_STUFF =>
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
|
IQUEUE.QUEUE(IQUEUE.RDPOS) := DBG_UART.RX_DATA;
|
IQUEUE.QUEUE(IQUEUE.RDPOS) := DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
DBG_CMD := DBG_STEP;
|
DBG_CMD := DBG_STEP;
|
end if;
|
end if;
|
when DBG_EXEC =>
|
when DBG_EXEC =>
|
if (OCDCR.DBGMODE='1') then
|
if (OCDCR.DBGMODE='1') then
|
OCD.SINGLESTEP:='1';
|
OCD.SINGLESTEP:='1';
|
CAN_FETCH:='0';
|
CAN_FETCH:='0';
|
IQUEUE.CNT := 0;
|
IQUEUE.CNT := 0;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
end if;
|
end if;
|
DBG_CMD := DBG_EXEC2;
|
DBG_CMD := DBG_EXEC2;
|
when DBG_EXEC2 =>
|
when DBG_EXEC2 =>
|
if (DBG_UART.RX_DONE='1') then
|
if (DBG_UART.RX_DONE='1') then
|
if (OCDCR.DBGMODE='0') then DBG_CMD := DBG_WAIT_CMD;
|
if (OCDCR.DBGMODE='0') then DBG_CMD := DBG_WAIT_CMD;
|
else
|
else
|
IQUEUE.QUEUE(IQUEUE.WRPOS) := DBG_UART.RX_DATA;
|
IQUEUE.QUEUE(IQUEUE.WRPOS) := DBG_UART.RX_DATA;
|
DBG_UART.RX_DONE:='0';
|
DBG_UART.RX_DONE:='0';
|
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
|
IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
|
IQUEUE.CNT := IQUEUE.CNT + 1;
|
IQUEUE.CNT := IQUEUE.CNT + 1;
|
DBG_CMD := DBG_EXEC3;
|
DBG_CMD := DBG_EXEC3;
|
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";
|
IRQ0(6):='0';
|
IRQ0(6):='0';
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='1') then
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='1') then
|
INTVECT:=x"0C";
|
INTVECT:=x"0C";
|
IRQ0(5):='0';
|
IRQ0(5):='0';
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='1') then
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='1') then
|
INTVECT:=x"0E";
|
INTVECT:=x"0E";
|
IRQ0(4):='0';
|
IRQ0(4):='0';
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='1') then
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='1') then
|
INTVECT:=x"10";
|
INTVECT:=x"10";
|
IRQ0(3):='0';
|
IRQ0(3):='0';
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='1') then
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='1') then
|
INTVECT:=x"12";
|
INTVECT:=x"12";
|
IRQ0(2):='0';
|
IRQ0(2):='0';
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='1') then
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='1') then
|
INTVECT:=x"14";
|
INTVECT:=x"14";
|
IRQ0(1):='0';
|
IRQ0(1):='0';
|
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='1') then
|
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='1') then
|
INTVECT:=x"16";
|
INTVECT:=x"16";
|
IRQ0(0):='0';
|
IRQ0(0):='0';
|
-- now priority level 2 interrupts
|
-- now priority level 2 interrupts
|
elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='0') then
|
elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='0') then
|
INTVECT:=x"08";
|
INTVECT:=x"08";
|
IRQ0(7):='0';
|
IRQ0(7):='0';
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='0') then
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='0') then
|
INTVECT:=x"0A";
|
INTVECT:=x"0A";
|
IRQ0(6):='0';
|
IRQ0(6):='0';
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='0') then
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='0') then
|
INTVECT:=x"0C";
|
INTVECT:=x"0C";
|
IRQ0(5):='0';
|
IRQ0(5):='0';
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='0') then
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='0') then
|
INTVECT:=x"0E";
|
INTVECT:=x"0E";
|
IRQ0(4):='0';
|
IRQ0(4):='0';
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='0') then
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='0') then
|
INTVECT:=x"10";
|
INTVECT:=x"10";
|
IRQ0(3):='0';
|
IRQ0(3):='0';
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='0') then
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='0') then
|
INTVECT:=x"12";
|
INTVECT:=x"12";
|
IRQ0(2):='0';
|
IRQ0(2):='0';
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='0') then
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='0') then
|
INTVECT:=x"14";
|
INTVECT:=x"14";
|
IRQ0(1):='0';
|
IRQ0(1):='0';
|
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='0') then
|
elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='0') then
|
INTVECT:=x"16";
|
INTVECT:=x"16";
|
IRQ0(0):='0';
|
IRQ0(0):='0';
|
-- now priority level 1 interrupts
|
-- now priority level 1 interrupts
|
elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='0') and IRQ0ENL(7)='1') then
|
elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='0') and IRQ0ENL(7)='1') then
|
INTVECT:=x"08";
|
INTVECT:=x"08";
|
IRQ0(7):='0';
|
IRQ0(7):='0';
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='0') and IRQ0ENL(6)='1') then
|
elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='0') and IRQ0ENL(6)='1') then
|
INTVECT:=x"0A";
|
INTVECT:=x"0A";
|
IRQ0(6):='0';
|
IRQ0(6):='0';
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='0') and IRQ0ENL(5)='1') then
|
elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='0') and IRQ0ENL(5)='1') then
|
INTVECT:=x"0C";
|
INTVECT:=x"0C";
|
IRQ0(5):='0';
|
IRQ0(5):='0';
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='0') and IRQ0ENL(4)='1') then
|
elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='0') and IRQ0ENL(4)='1') then
|
INTVECT:=x"0E";
|
INTVECT:=x"0E";
|
IRQ0(4):='0';
|
IRQ0(4):='0';
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='0') and IRQ0ENL(3)='1') then
|
elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='0') and IRQ0ENL(3)='1') then
|
INTVECT:=x"10";
|
INTVECT:=x"10";
|
IRQ0(3):='0';
|
IRQ0(3):='0';
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='0') and IRQ0ENL(2)='1') then
|
elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='0') and IRQ0ENL(2)='1') then
|
INTVECT:=x"12";
|
INTVECT:=x"12";
|
IRQ0(2):='0';
|
IRQ0(2):='0';
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='0') and IRQ0ENL(1)='1') then
|
elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='0') and IRQ0ENL(1)='1') then
|
INTVECT:=x"14";
|
INTVECT:=x"14";
|
IRQ0(1):='0';
|
IRQ0(1):='0';
|
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;
|
|
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 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" =>
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
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;
|
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
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
when x"8" => ------------------------------------------------------------------------- LDX r1,rr2,X instruction
|
when x"8" => ------------------------------------------------------------------------- LDX r1,rr2,X instruction
|
when x"9" => -------------------------------------------------------------------------- LEA r1,r2,X instruction
|
when x"9" => -------------------------------------------------------------------------- LEA r1,r2,X instruction
|
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;
|
end if;
|
end if;
|
|
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 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;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 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
|
PC := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
PC := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
else
|
else
|
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;
|
CPU_STATE := CPU_DJNZ;
|
CPU_STATE := CPU_DJNZ;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"3") then -------------------------------------------- column 3 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"3") then -------------------------------------------- column 3 instructions
|
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;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"1") then -------------------------------------------- column 1 instructions
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"1") then -------------------------------------------- column 1 instructions
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
|
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;
|
end if;
|
end if;
|
|
|
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
--**************************************************************************************************************************--
|
--**************************************************************************************************************************--
|
-- 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
|
when x"2" =>
|
when x"2" =>
|
ATM_COUNTER := 0;
|
ATM_COUNTER := 0;
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"3" =>
|
when x"3" =>
|
CPU_STATE := CPU_ILLEGAL;
|
CPU_STATE := CPU_ILLEGAL;
|
when x"4" =>
|
when x"4" =>
|
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
|
CPU_FLAGS.C := '1';
|
CPU_FLAGS.C := '1';
|
NUM_BYTES := 1;
|
NUM_BYTES := 1;
|
when x"E" => ---------------------------------------------------------------------------------- CCF instruction
|
when x"E" => ---------------------------------------------------------------------------------- CCF instruction
|
CPU_FLAGS.C := not CPU_FLAGS.C;
|
CPU_FLAGS.C := not CPU_FLAGS.C;
|
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
|
if (OCDCR.DBGACK='1') then
|
if (OCDCR.DBGACK='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
if (DBG_UART.TX_EMPTY='1') then
|
DBG_UART.TX_DATA:=x"FF";
|
DBG_UART.TX_DATA:=x"FF";
|
DBG_UART.TX_EMPTY:='0';
|
DBG_UART.TX_EMPTY:='0';
|
end if;
|
end if;
|
end if;
|
end if;
|
if (OCDCR.BRKLOOP='0') then -- if loop on BRK is disabled
|
if (OCDCR.BRKLOOP='0') then -- if loop on BRK is disabled
|
OCDCR.DBGMODE := '1'; -- set DBGMODE halting CPU
|
OCDCR.DBGMODE := '1'; -- set DBGMODE halting CPU
|
end if;
|
end if;
|
else
|
else
|
NUM_BYTES := 1; -- remove the instruction from queue (execute as a NOP)
|
NUM_BYTES := 1; -- remove the instruction from queue (execute as a NOP)
|
end if;
|
end if;
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F9" or
|
elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F9" or
|
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;
|
CPU_FLAGS.H := ALU_FLAGS.H;
|
CPU_FLAGS.H := ALU_FLAGS.H;
|
CPU_FLAGS.D := TEMP_OP(1);
|
CPU_FLAGS.D := TEMP_OP(1);
|
elsif (TEMP_OP=ALU_CP or TEMP_OP=ALU_CPC) then
|
elsif (TEMP_OP=ALU_CP or TEMP_OP=ALU_CPC) 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;
|
elsif (TEMP_OP/=ALU_LD) then
|
elsif (TEMP_OP/=ALU_LD) then
|
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
|
CPU_FLAGS.V := '0';
|
CPU_FLAGS.V := '0';
|
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_SWAP) then
|
elsif (TEMP_OP=LU2_SWAP) then
|
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_DA) then
|
elsif (TEMP_OP=LU2_DA) then
|
CPU_FLAGS.C := ALU_FLAGS.C;
|
CPU_FLAGS.C := ALU_FLAGS.C;
|
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_LD) then
|
elsif (TEMP_OP=LU2_LD) then
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.V := ALU_FLAGS.V;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.S := ALU_FLAGS.S;
|
CPU_FLAGS.Z := CPU_FLAGS.Z and ALU_FLAGS.Z;
|
CPU_FLAGS.Z := CPU_FLAGS.Z and ALU_FLAGS.Z;
|
elsif (TEMP_OP/=LU2_CLR) then
|
elsif (TEMP_OP/=LU2_CLR) 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;
|
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';
|
CAN_FETCH := '1';
|
CAN_FETCH := '1';
|
FETCH_ADDR := x"0000";
|
FETCH_ADDR := x"0000";
|
RXSYNC1 <= '1';
|
RXSYNC1 <= '1';
|
RXSYNC2 <= '1';
|
RXSYNC2 <= '1';
|
DBG_UART.LAST_SMP := '1';
|
DBG_UART.LAST_SMP := '1';
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IQUEUE.FETCH_STATE := F_ADDR;
|
IRQE := '0';
|
IRQE := '0';
|
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";
|
OCDCR.RST := '0';
|
OCDCR.RST := '0';
|
ATM_COUNTER := 0;
|
ATM_COUNTER := 0;
|
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;
|
|
|