OpenCores
URL https://opencores.org/ocsvn/fpz8/fpz8/trunk

Subversion Repositories fpz8

[/] [fpz8_cpu_v1.vhd] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 fabiop
-- FPz8 mk1 v0.99
2 2 fabiop
-- Zilog Z8 Encore! 100% compatible softcore
3
-- Author:      Fábio Pereira (fabio.jve@gmail.com)
4 3 fabiop
-- Version: 0.99        Nov, 24th, 2016 (changed LDWX instruction, interrupts, condition code function, debugger command processor)
5
-- Version: 0.91        Nov, 15th, 2016
6 2 fabiop
-- Version:     0.9             Nov, 11th, 2016
7
 
8 3 fabiop
-- FPz8 is a softcore almost 100% object-code compatible with the Z8 encore microcontroller line. Current implementation includes 
9 2 fabiop
-- 2kb of file registers (RAM), 16kb of program memory (using FPGA RAM), 8 vectored interrupts with programmable priority, 
10
-- full-featured onchip debugger 100% compatible with Zilog's OCD and ZDS-II IDE.
11
-- It was designed to work as a SoC and everything (except the USB chip) fits inside a single FPGA (I have used an Altera 
12
-- Cyclone IV EP4CE6 device). The debugger connection makes use of a serial-to-USB chip (it is part of the low-cost FPGA 
13
-- board used on the project).
14
-- In a near future I plan to add some more features to the device (such as a timer and maybe other peripherals).
15 3 fabiop
-- The idea behind the FPz8 was to learn more on VHDL and FPGAs (this is my second design using these technologies). I also 
16
-- believe FPz8 can be a very interesting tool for learning/teaching VHDL, computing and microprocessors/microcontrollers 
17 2 fabiop
-- programming.
18
 
19
-- 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).
20
-- If you want to contribute to the project, contact me and share your thoughts.
21
-- Don't forget to credit the author!
22
 
23
-- Note: currently there are only a few SFRs physically implemented, they are:
24
-- 0xFC0 - IRQ0
25
-- 0xFC1 - IRQ0ENH
26
-- 0xFC2 - IRQ0ENL
27
-- 0xFCF - IRQCTL
28
-- 0xFD2 - PAIN
29
-- 0xFD3 - PAOUT
30
-- 0xFF8 - FCTL
31
-- 0xFFC - FLAGS
32
-- 0xFFD - RP
33
-- 0xFFE - SPH
34
-- 0xFFF - SPL
35
 
36
-- What else is missing from the original architecture?
37 3 fabiop
-- A: no watchdog (WDT instruction runs as a NOP), no LDE and LDEI instructions (data memory related), no option bytes,
38
--    no data memory related debug commands, no CRC debug command, no ID bytes
39 2 fabiop
 
40 3 fabiop
-- FPz8 was tested on an EP4CE6 mini board (50MHz clock)
41 2 fabiop
-- http://www.ebay.com/itm/EP4CE6-Mini-Board-USB-Blaster-Altera-Cyclone-IV-FPGA-CPLD-Nano-Size-
42
 
43
-- This work is licensed under the Creative Commons Attribution 4.0 International License.
44
-- To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/.
45
 
46
library ieee ;
47
use ieee.std_logic_1164.all ;
48
use ieee.numeric_std.all;
49
use ieee.std_logic_unsigned.all ;
50
 
51
entity fpz8_cpu_v1 IS
52
        port
53
        (
54
                IAB                     : buffer std_logic_vector(15 downto 0);  -- instruction address bus (16 bits)
55
                IDB                     : in std_logic_vector(7 downto 0);               -- instruction data bus (8 bits)
56 3 fabiop
                IWDB            : out std_logic_vector(7 downto 0);              -- instruction write data bus (8 bits)
57
                FRAB            : buffer std_logic_vector(11 downto 0);  -- file register address bus (12 bits)
58
                FRIDB           : in std_logic_vector(7 downto 0);               -- memory input data bus (8 bits)
59
                FRODB           : out std_logic_vector(7 downto 0);              -- memory output data bus (8 bits)
60 2 fabiop
                RIDB            : in std_logic_vector(7 downto 0);               -- register input data bus (8 bits)
61
                RODB            : out std_logic_vector(7 downto 0);              -- register output data bus (8 bits)            
62
                PGM_WR          : out std_logic;                                                -- program memory write enable
63
                WR                      : buffer std_logic;                                             -- write enable
64
                REG_SEL         : buffer std_logic;                                             -- SFR select (addresses F00 to FFF, except internal registers)
65
                MEM_SEL         : buffer std_logic;                                             -- memory select
66
                INT0            : in std_logic;                                                 -- interrupt 0 input (vector 0x0016)
67
                INT1            : in std_logic;                                                 -- interrupt 1 input (vector 0x0014)
68
                INT2            : in std_logic;                                                 -- interrupt 2 input (vector 0x0012)
69
                INT3            : in std_logic;                                                 -- interrupt 3 input (vector 0x0010)
70
                INT4            : in std_logic;                                                 -- interrupt 4 input (vector 0x000E)
71
                INT5            : in std_logic;                                                 -- interrupt 5 input (vector 0x000C)
72
                INT6            : in std_logic;                                                 -- interrupt 6 input (vector 0x000A)
73 3 fabiop
                INT7            : in std_logic;                                                 -- interrupt 7 input (vector 0x0008)
74 2 fabiop
                DBG_RX          : in std_logic;                                                 -- debugger receive input
75
                DBG_TX          : buffer std_logic;                                             -- debugger transmit output
76
                PAOUT           : out std_logic_vector(7 downto 0);              -- port A output data
77
                PAIN            : in std_logic_vector(7 downto 0);               -- port A input data
78
                CLK                     : in std_logic;                                                 -- main clock
79 3 fabiop
                CLK_OUT         : buffer std_logic;                                             -- main clock output
80
                CLK_OUTN        : out std_logic;                                                -- main inverted clock output
81 2 fabiop
                STOP            : buffer std_logic;                                             -- stop output   
82 3 fabiop
                RESET_OUT       : out std_logic;                                                -- reset output
83 2 fabiop
                RESET           : in std_logic                                                  -- CPU reset                    
84
        );
85
end fpz8_cpu_v1;
86
 
87
architecture cpu of fpz8_cpu_v1 is
88
 
89
type Tinstqueue is array (0 TO 7) of std_logic_vector(7 downto 0);
90
type Tflags is record
91
        C,Z,S,V,D,H,F2,F1                       : std_logic;
92
end record;
93
shared variable CPU_FLAGS, ALU_FLAGS            : Tflags;
94
shared variable ALU_NOUPDATE                            : std_logic;
95
shared variable IRQE                                            : std_logic;
96
shared variable IRQ0                                            : std_logic_vector(7 downto 0);          -- interrupts 0-7 flags
97
shared variable IRQ0ENH,IRQ0ENL                         : std_logic_vector(7 downto 0);          -- interrupts 0-7 enable high and low
98
shared variable SP                                                      : std_logic_vector(11 downto 0); -- stack pointer
99
shared variable RP                                                      : std_logic_vector(7 downto 0);          -- register pointer
100
shared variable FCTL                                            : std_logic_vector(7 downto 0);          -- flash control
101
shared variable PAOUT_BUFFER                            : std_logic_vector(7 downto 0);
102
signal                  RXSYNC1, RXSYNC2                        : std_logic;
103
ATTRIBUTE preserve                                                      : boolean;
104
ATTRIBUTE preserve OF RXSYNC1                           : signal IS true;
105
ATTRIBUTE preserve OF RXSYNC2                           : signal IS true;
106 3 fabiop
signal IRQ0_LATCH                                                       : std_logic_vector(7 downto 0);          -- current state of IRQ inputs
107
attribute preserve of IRQ0_LATCH                        : signal is true;
108 2 fabiop
 
109
constant ALU_ADD        : std_logic_vector(3 downto 0):=x"0";     -- CZSVH D=0
110
constant ALU_ADC        : std_logic_vector(3 downto 0):=x"1";    -- CZSVH D=0
111
constant ALU_SUB        : std_logic_vector(3 downto 0):=x"2";    -- CZSVH D=1
112
constant ALU_SBC        : std_logic_vector(3 downto 0):=x"3";    -- CZSVH D=1
113
constant ALU_OR         : std_logic_vector(3 downto 0):=x"4";    -- ZS V=0
114
constant ALU_AND        : std_logic_vector(3 downto 0):=x"5";    -- ZS V=0
115
constant ALU_TCM        : std_logic_vector(3 downto 0):=x"6";    -- ZS V=0
116
constant ALU_TM         : std_logic_vector(3 downto 0):=x"7";    -- ZS V=0
117
constant ALU_CPC        : std_logic_vector(3 downto 0):=x"9";    -- CZSV
118
constant ALU_CP         : std_logic_vector(3 downto 0):=x"A";    -- CZSV
119
constant ALU_XOR        : std_logic_vector(3 downto 0):=x"B";    -- ZS V=0
120
constant ALU_BSWAP  : std_logic_vector(3 downto 0):=x"D";        -- ZS V=0
121
constant ALU_LD         : std_logic_vector(3 downto 0):=x"E";    -- Load does not change any flag
122
 
123
constant LU2_RLC        : std_logic_vector(3 downto 0):=x"1";    -- CZSV
124
constant LU2_INC        : std_logic_vector(3 downto 0):=x"2";    -- ZSV
125
constant LU2_DEC        : std_logic_vector(3 downto 0):=x"3";    -- ZSV
126
constant LU2_DA         : std_logic_vector(3 downto 0):=x"4";    -- CZS
127
constant LU2_COM        : std_logic_vector(3 downto 0):=x"6";    -- ZS V=0
128
constant LU2_LD         : std_logic_vector(3 downto 0):=x"7";    -- Load does not change any flag
129
constant LU2_RL         : std_logic_vector(3 downto 0):=x"9";    -- CZSV
130
constant LU2_SRL        : std_logic_vector(3 downto 0):=x"A";    -- CZSV
131
constant LU2_CLR        : std_logic_vector(3 downto 0):=x"B";    -- Clear does not change any flag
132
constant LU2_RRC        : std_logic_vector(3 downto 0):=x"C";    -- CZSV
133
constant LU2_SRA        : std_logic_vector(3 downto 0):=x"D";    -- CZSV
134
constant LU2_RR         : std_logic_vector(3 downto 0):=x"E";    -- CZSV
135
constant LU2_SWAP       : std_logic_vector(3 downto 0):=x"F";    -- ZS
136
 
137
-- Debug commands
138
constant DBGCMD_READ_REV                : std_logic_vector(7 downto 0):=x"00";
139
constant DBGCMD_READ_STATUS             : std_logic_vector(7 downto 0):=x"02";
140
constant DBGCMD_READ_RUNCOUNTER : std_logic_vector(7 downto 0):=x"03";
141
constant DBGCMD_WRITE_CTRL              : std_logic_vector(7 downto 0):=x"04";
142
constant DBGCMD_READ_CTRL               : std_logic_vector(7 downto 0):=x"05";
143
constant DBGCMD_WRITE_PC                : std_logic_vector(7 downto 0):=x"06";
144
constant DBGCMD_READ_PC                 : std_logic_vector(7 downto 0):=x"07";
145
constant DBGCMD_WRITE_REG               : std_logic_vector(7 downto 0):=x"08";
146
constant DBGCMD_READ_REG                : std_logic_vector(7 downto 0):=x"09";
147
constant DBGCMD_WRITE_PROGRAM   : std_logic_vector(7 downto 0):=x"0A";
148
constant DBGCMD_READ_PROGRAM    : std_logic_vector(7 downto 0):=x"0B";
149
constant DBGCMD_READ_CRC                : std_logic_vector(7 downto 0):=x"0E";
150
constant DBGCMD_STEP                    : std_logic_vector(7 downto 0):=x"10";
151
constant DBGCMD_STUFF                   : std_logic_vector(7 downto 0):=x"11";
152
constant DBGCMD_EXEC                    : std_logic_vector(7 downto 0):=x"12";
153
 
154
-- DATAWRITE controls where data to be written actually goes (an internal register, an external register (through register data bus) or RAM)
155
procedure DATAWRITE
156
        (       ADDRESS : in std_logic_vector(11 downto 0);
157
                DATA    : in std_logic_vector(7 downto 0)) is
158
begin
159
        if (ADDRESS>=x"F00") then               ----------------------------------------------- it is a SFR address
160
                if (ADDRESS=x"FFC") then        ---------------------------------------------------- FLAGS register
161
                        CPU_FLAGS.C := DATA(7);
162
                        CPU_FLAGS.Z := DATA(6);
163
                        CPU_FLAGS.S := DATA(5);
164
                        CPU_FLAGS.V := DATA(4);
165
                        CPU_FLAGS.D := DATA(3);
166
                        CPU_FLAGS.H := DATA(2);
167
                        CPU_FLAGS.F2 := DATA(1);
168
                        CPU_FLAGS.F1 := DATA(0);
169
                elsif (ADDRESS=x"FFD") then RP := DATA; ------------------------------------------- RP register
170
                elsif (ADDRESS=x"FFE") then SP(11 downto 8) := DATA(3 downto 0); -------------- SPH register
171
                elsif (ADDRESS=x"FFF") then SP(7 downto 0) := DATA;      ------------------------------ SPL register
172
                elsif (ADDRESS=x"FF8") then     ----------------------------------------------------- FCTL register
173
                        if (DATA=x"73") then FCTL:=x"01";
174
                        elsif (DATA=x"8C" and FCTL=x"01") then FCTL:=x"03";
175
                        elsif (DATA=x"95") then FCTL:=x"04";
176
                        else FCTL:=x"00";
177
                        end if;
178
                elsif (ADDRESS=x"FC0") then     IRQ0 := DATA; --------------------------------------- IRQ0 register
179
                elsif (ADDRESS=x"FC1") then IRQ0ENH := DATA;    ------------------------------ IRQ0ENH register
180
                elsif (ADDRESS=x"FC2") then IRQ0ENL := DATA;    ------------------------------ IRQ0ENL register
181
                elsif (ADDRESS=x"FCF") then     IRQE := DATA(7);        ------------------------------- IRQCTL register
182
                elsif (ADDRESS=x"FD3") then ---------------------------------------------------- PAOUT register
183
                        PAOUT <= DATA;
184
                        PAOUT_BUFFER := DATA;
185 3 fabiop
                else -- if it is not an internal SFR but ADDRESS>=0xF00 then it is an external register
186
                        REG_SEL <= '1'; -- enable external register select
187
                        RODB <= DATA;   -- output data on register output data bus
188 2 fabiop
                end if;
189 3 fabiop
        else    -- if ADDRESS < 0xF00 then it is a RAM register
190
                MEM_SEL <= '1';         -- enable external memory select
191
                FRODB <= DATA;          -- output data on file register output data bus
192 2 fabiop
        end if;
193
end datawrite;
194
 
195
-- DATAREAD controls where the data to be read actually comes from (an internal register, an external register (through register data bus) or RAM)
196
impure function DATAREAD
197
        (ADDRESS        : in std_logic_vector(11 downto 0))
198
        return std_logic_vector is
199
begin
200
        if (ADDRESS>=x"F00") then       -------------------------------- it is a SFR address
201
                if (ADDRESS=x"FFC") then        --------------------------------- FLAGS register
202
                        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);
203
                elsif (ADDRESS=x"FFD") then return RP;  ------------------------ RP register
204
                elsif (ADDRESS=x"FFE") then     ----------------------------------- SPH register
205
                        return "0000" & SP(11 downto 8);
206
                elsif (ADDRESS=x"FFF") then return SP(7 downto 0);       ----------- SPL register
207
                elsif (ADDRESS=x"FF8") then return FCTL;        ------------------ FCTL register
208
                elsif (ADDRESS=x"FC0") then     return IRQ0;    ------------------ IRQ0 register
209
                elsif (ADDRESS=x"FC1") then return IRQ0ENH;     --------------- IRQ0ENH register
210
                elsif (ADDRESS=x"FC2") then return IRQ0ENL;     --------------- IRQ0ENL register
211
                elsif (ADDRESS=x"FCF") then return IRQE&"0000000";      -------- IRQCTL register
212
                elsif (ADDRESS=x"FD2") then return PAIN;        ------------------ PAIN register
213
                elsif (ADDRESS=x"FD3") then return PAOUT_BUFFER;        --------- PAOUT register
214
                else
215
                        REG_SEL <= '1';
216
                        return RIDB;
217
                end if;
218
        else
219
                MEM_SEL <= '1';
220 3 fabiop
                return FRIDB;
221 2 fabiop
        end if;
222
end DATAREAD;
223
 
224
-- CONDITIONCODE returns the result of a logical condition (for conditional jumps)
225
function CONDITIONCODE
226
        (       CONDITION       : in std_logic_vector(3 downto 0)) return STD_LOGIC is
227
begin
228
        case CONDITION is
229
                when x"0" =>
230
                        return '0';
231
                when x"1" =>
232 3 fabiop
                        return CPU_FLAGS.S xor CPU_FLAGS.V;
233 2 fabiop
                when x"2" =>
234 3 fabiop
                        return CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V);
235 2 fabiop
                when x"3" =>
236 3 fabiop
                        return CPU_FLAGS.C or CPU_FLAGS.Z;
237 2 fabiop
                when x"4" =>
238 3 fabiop
                        return CPU_FLAGS.V;
239 2 fabiop
                when x"5" =>
240 3 fabiop
                        return CPU_FLAGS.S;
241 2 fabiop
                when x"6" =>
242 3 fabiop
                        return CPU_FLAGS.Z;
243 2 fabiop
                when x"7" =>
244 3 fabiop
                        return CPU_FLAGS.C;
245 2 fabiop
                when x"8" =>
246
                        return '1';
247
                when x"9" =>
248 3 fabiop
                        return NOT (CPU_FLAGS.S xor CPU_FLAGS.V);
249 2 fabiop
                when x"A" =>
250 3 fabiop
                        return NOT (CPU_FLAGS.Z or (CPU_FLAGS.S xor CPU_FLAGS.V));
251 2 fabiop
                when x"B" =>
252 3 fabiop
                        return (NOT CPU_FLAGS.C) AND (NOT CPU_FLAGS.Z);
253 2 fabiop
                when x"C" =>
254 3 fabiop
                        return NOT CPU_FLAGS.V;
255 2 fabiop
                when x"D" =>
256 3 fabiop
                        return NOT CPU_FLAGS.S;
257 2 fabiop
                when x"E" =>
258 3 fabiop
                        return NOT CPU_FLAGS.Z;
259 2 fabiop
                when others =>
260 3 fabiop
                        return NOT CPU_FLAGS.C;
261 2 fabiop
        end case;
262
end CONDITIONCODE;
263
 
264
-- ADDRESSER12 generates a 12-bit address (it decides when to use escaped addressing mode)
265
function ADDRESSER12
266
        (       ADDR    : in std_logic_vector(11 downto 0)) return std_logic_vector is
267
begin
268
        if (ADDR(11 downto 4)=x"EE") then               -- escaped addressing mode (work register)
269
                return RP(3 downto 0) & RP(7 downto 4) & ADDR(3 downto 0);
270
        elsif (ADDR(11 downto 8)=x"E") then             -- escaped addressing mode (register)
271
                return RP(3 downto 0) & ADDR(7 downto 0);
272
        else return ADDR;                                               -- full address
273
        end if;
274
end ADDRESSER12;
275
 
276
-- ADDRESSER8 generates a 12-bit address from an 8-bit address (it decides when to use escaped addressing mode)
277
function ADDRESSER8
278
        (       ADDR    : in std_logic_vector(7 downto 0)) return std_logic_vector is
279
begin
280
        if (ADDR(7 downto 4)=x"E") then         -- escaped addressing mode (register)
281
                return RP(3 downto 0) & RP(7 downto 4) & ADDR(3 downto 0);
282
        else return RP(3 downto 0) & ADDR(7 downto 0);    -- full address
283
        end if;
284
end ADDRESSER8;
285
 
286 3 fabiop
-- ADDRESSER4 generates a 12-bit address from a 4-bit address (using RP register)
287 2 fabiop
function ADDRESSER4
288
        (       ADDR    : in std_logic_vector(3 downto 0)) return std_logic_vector is
289
begin
290
        return RP(3 downto 0) & RP(7 downto 4) & ADDR;
291
end ADDRESSER4;
292
 
293
-- 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
294
function ALU
295
        (       ALU_OP  : in std_logic_vector(3 downto 0);
296
                OPER1   : in std_logic_vector(7 downto 0);
297
                OPER2   : in std_logic_vector(7 downto 0);
298
                CIN             : in STD_LOGIC) return std_logic_vector is
299
variable RESULT : std_logic_vector(7 downto 0);
300
variable HALF1,HALF2    : std_logic_vector(4 downto 0);
301
begin
302
        ALU_NOUPDATE := '0';
303
        case ALU_OP is
304
                when ALU_ADD =>         -- ADD operation **************************************************
305
                        HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0));
306
                        ALU_FLAGS.H := HALF1(4);
307
                        HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
308
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
309
                        ALU_FLAGS.C := HALF2(4);
310
                        if (OPER1(7)=OPER2(7)) then
311
                                if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
312
                                end if;
313
                        else ALU_FLAGS.V:='0';
314
                        end if;
315
                when ALU_ADC =>         -- ADC operation **************************************************
316
                        HALF1 := ('0'&OPER1(3 downto 0))+('0'&OPER2(3 downto 0)+(CIN));
317
                        ALU_FLAGS.H := HALF1(4);
318
                        HALF2 := ('0'&OPER1(7 downto 4))+('0'&OPER2(7 downto 4))+HALF1(4);
319
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
320
                        ALU_FLAGS.C := HALF2(4);
321
                        if (OPER1(7)=OPER2(7)) then
322
                                if (OPER1(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
323
                                end if;
324
                        else ALU_FLAGS.V:='0';
325
                        end if;
326
                when ALU_SUB =>         -- SUB operation **************************************************
327
                        HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
328
                        ALU_FLAGS.H := (HALF1(4));
329
                        HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
330
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
331
                        ALU_FLAGS.C := (HALF2(4));
332
                        if (OPER1(7)/=OPER2(7)) then
333
                                if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
334
                                end if;
335
                        else ALU_FLAGS.V:='0';
336
                        end if;
337
                when ALU_SBC =>         -- SBC operation **************************************************
338
                        HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
339
                        ALU_FLAGS.H := (HALF1(4));
340
                        HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
341
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
342
                        ALU_FLAGS.C := (HALF2(4));
343
                        if (OPER1(7)/=OPER2(7)) then
344
                                if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
345
                                end if;
346
                        else ALU_FLAGS.V:='0';
347
                        end if;
348
                when ALU_OR =>  -- Logical or operation ***********************************************
349
                        RESULT := OPER1 or OPER2;
350
                when ALU_AND => -- Logical AND operation **********************************************
351
                        RESULT := OPER1 AND OPER2;
352
                when ALU_TCM => -- Test Complement Mask operation *************************************
353
                        RESULT := (NOT OPER1) AND OPER2;
354
                        ALU_NOUPDATE := '1';
355
                when ALU_TM =>  -- Test Mask operation ************************************************
356
                        RESULT := OPER1 AND OPER2;
357
                        ALU_NOUPDATE := '1';
358
                when ALU_CPC =>         -- CPC operation **************************************************
359
                        HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)))-CIN;
360
                        ALU_FLAGS.H := (HALF1(4));
361
                        HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
362
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
363
                        ALU_FLAGS.C := (HALF2(4));
364
                        if (OPER1(7)/=OPER2(7)) then
365
                                if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
366
                                end if;
367
                        else ALU_FLAGS.V:='0';
368
                        end if;
369
                        ALU_NOUPDATE := '1';
370
                when ALU_CP =>  -- Compare operation **************************************************
371
                        HALF1 := ('0'&OPER1(3 downto 0))-('0'&(OPER2(3 downto 0)));
372
                        ALU_FLAGS.H := (HALF1(4));
373
                        HALF2 := ('0'&OPER1(7 downto 4))-('0'&(OPER2(7 downto 4)))-HALF1(4);
374
                        RESULT := HALF2(3 downto 0) & HALF1(3 downto 0);
375
                        ALU_FLAGS.C := (HALF2(4));
376
                        if (OPER1(7)/=OPER2(7)) then
377
                                if (OPER1(7)=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
378
                                end if;
379
                        else ALU_FLAGS.V:='0';
380
                        end if;
381
                        ALU_NOUPDATE := '1';
382
                when ALU_XOR => -- Logical xor operation **********************************************
383
                        RESULT := OPER1 xor OPER2;
384
                when ALU_BSWAP =>       -- Bit Swap operation *********************************************
385
                        RESULT := OPER2(0)&OPER2(1)&OPER2(2)&OPER2(3)&OPER2(4)&OPER2(5)&OPER2(6)&OPER2(7);
386
                when others =>  -- Load operation *****************************************************
387
                        RESULT := OPER2;
388
 
389
        end case;
390
        if (RESULT(7 downto 0)=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
391
        end if;
392
        ALU_FLAGS.S := RESULT(7);
393
        return RESULT(7 downto 0);
394
end ALU;
395
 
396
-- LU2 is the second logic unit, it performs mostly logical operations not covered by the ALU
397
function LU2
398
        (       LU2_OP  : in std_logic_vector(3 downto 0);
399
                OPER    : in std_logic_vector(7 downto 0);
400
                DIN             : in std_logic;
401
                HIN             : in std_logic;
402
                CIN             : in std_logic) return std_logic_vector is
403
variable RESULT : std_logic_vector(7 downto 0);
404
begin
405
        case LU2_OP is
406
                when LU2_RLC =>         -- RLC operation **************************************************
407
                        ALU_FLAGS.C := OPER(7);
408
                        RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&CIN;
409
                when LU2_INC =>         -- INC operation **************************************************
410
                        RESULT := OPER+1;
411
                        if (RESULT=x"00") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
412
                        end if;
413
                when LU2_DEC =>         -- DEC operation **************************************************
414
                        RESULT := OPER-1;
415
                        if (RESULT=x"FF") then ALU_FLAGS.C:='1'; else ALU_FLAGS.C:='0';
416
                        end if;
417
                when LU2_DA =>          -- DA operation ***************************************************
418
                        if (DIN='0') then        -- decimal adjust following an add operation
419
                                if (OPER(3 downto 0)>x"9" or HIN='1') then
420
                                        RESULT := ALU(ALU_ADD,OPER,x"06",'0');
421
                                else RESULT := OPER;
422
                                end if;
423
                                if (RESULT(7 downto 4)>x"9" or ALU_FLAGS.C='1') then
424
                                        RESULT := ALU(ALU_ADD,RESULT,x"60",'0');
425
                                end if;
426
                        else    -------------- decimal adjust following a sub operation
427
                        end if;
428
                when LU2_COM =>         -- COM operation **************************************************
429
                        RESULT := NOT OPER;
430
                when LU2_RL =>          -- RL operation ***************************************************
431
                        ALU_FLAGS.C := OPER(7);
432
                        RESULT := OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1)&OPER(0)&ALU_FLAGS.C;
433
                when LU2_SRL =>         -- SRL operation **************************************************
434
                        ALU_FLAGS.C := OPER(0);
435
                        RESULT := '0'&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
436
                when LU2_RRC =>         -- RRC operation **************************************************
437
                        ALU_FLAGS.C := OPER(0);
438
                        RESULT := CIN&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
439
                when LU2_RR =>          -- RR operation ***************************************************
440
                        ALU_FLAGS.C := OPER(0);
441
                        RESULT := ALU_FLAGS.C&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
442
                when LU2_SRA =>         -- SRA operation **************************************************
443
                        ALU_FLAGS.C := OPER(0);
444
                        RESULT := OPER(7)&OPER(7)&OPER(6)&OPER(5)&OPER(4)&OPER(3)&OPER(2)&OPER(1);
445
                when LU2_SWAP =>        -- SWAP operation *************************************************
446
                        RESULT := OPER(3)&OPER(2)&OPER(1)&OPER(0)&OPER(7)&OPER(6)&OPER(5)&OPER(4);
447
                when LU2_LD =>          -- LOAD operation *************************************************
448
                        RESULT := OPER;
449
                when others =>          -- CLR operation **************************************************
450
                        RESULT := x"00";
451
        end case;
452
        if (OPER(7)/=RESULT(7)) then ALU_FLAGS.V :='1'; else ALU_FLAGS.V :='0';
453
        end if;
454
        if (RESULT=x"00") then ALU_FLAGS.Z := '1'; else ALU_FLAGS.Z := '0';
455
        end if;
456
        ALU_FLAGS.S := RESULT(7);
457
        return RESULT;
458
end LU2;
459
 
460
-- ADDER16 adds a signed 8-bit offset to a 16-bit address
461
function ADDER16
462
        (       ADDR16  : in std_logic_vector(15 downto 0);
463
                OFFSET  : in std_logic_vector(7 downto 0)) return std_logic_vector is
464
begin
465
        if (OFFSET(7)='0') then return ADDR16 + (x"00" & OFFSET);
466
        else return ADDR16 + (x"FF" & OFFSET);
467
        end if;
468
end ADDER16;
469
 
470
begin
471 3 fabiop
        clock_out: process(CLK,RESET)
472
        variable CKDIVIDER              : integer range 0 to 2;
473 2 fabiop
        begin
474 3 fabiop
                if (RESET='1') then
475
                        CKDIVIDER := 0;
476
                        CLK_OUTN <= '1';
477
                        CLK_OUT <= '0';
478
                elsif (rising_edge(CLK)) then
479
                        CLK_OUTN <= '1';
480
                        CLK_OUT <= '0';
481
                        CKDIVIDER := CKDIVIDER + 1;
482
                        if (CKDIVIDER=0) then    -- main clock (50MHz) is divided by 3, resulting in a 16.66MHz system clock
483
                                CLK_OUT <= '1';
484
                                CLK_OUTN <= '0';
485
                        end if;
486
                end if;
487
        end process;    -- clock_out process
488 2 fabiop
        -- main process controls debugging and instruction fetching and decoding along
489 3 fabiop
        main: process (CLK_OUT,RESET,DBG_RX)
490 2 fabiop
        -- CPU state machine
491
        type Tcpu_state is (
492
                CPU_DECOD,
493 3 fabiop
                CPU_INDRR,                                              -- indirect rr mode
494
                CPU_MUL, CPU_MUL1, CPU_MUL2,    -- MUL instruction
495
                CPU_XADTOM,                                             -- address with offset to memory
496
                CPU_MTOXAD, CPU_MTOXAD2,                -- memory to address with offset
497
                CPU_XRTOM,                                              -- register with offset to memory
498
                CPU_XRRTORR, CPU_XRRTORR2,              -- register pair with offset to register pair
499 2 fabiop
                CPU_XRRTORR3, CPU_XRRTORR4,
500
                CPU_IMTOIRR, CPU_MTOIRR,                -- indirect and direct to indirect register pair addressing mode
501 3 fabiop
                CPU_IRRS, CPU_IRRS2,                    -- indirect register pair as source
502 2 fabiop
                CPU_XRRD, CPU_XRRD2, CPU_XRRD3, -- indexed rr pair as destination
503
                CPU_XRRS, CPU_XRRS2, CPU_XRRS3, -- indexed rr pair as source
504
                CPU_IND1, CPU_IND2,                             -- indirect memory access
505
                CPU_ISMD1,                                              -- indirect source to memory destination
506
                CPU_TMA,                                                -- Two memory access instructions (register to/with register)
507
                CPU_OMA,                                                -- One memory access instructions (immediate to/with register)
508
                CPU_OMA2,                                               -- One memory access instructions (immediate to/with register) logic unit related
509
                CPU_DMAB,                                               -- Decrement address bus (for word access)
510 3 fabiop
                CPU_LDW, CPU_LDW2, CPU_LDW3,    -- load word instruction
511
                CPU_LDW4, CPU_LDW5,
512
                CPU_LDPTOIM, CPU_LDPTOIM2,              -- load program to indirect memory
513
                CPU_LDPTOM, CPU_LDPTOM2,                -- load program to memory
514
                CPU_LDPTOM3, CPU_LDPTOM4,
515
                CPU_LDMTOP, CPU_LDMTOP2,                -- load memory to program
516
                CPU_BIT,                                                -- BIT instruction
517
                CPU_IBTJ, CPU_BTJ,                              -- BTJ instruction
518
                CPU_DJNZ,                                               -- DJNZ instruction
519
                CPU_INDJUMP, CPU_INDJUMP2,              -- indirect JP
520
                CPU_TRAP, CPU_TRAP2,                    -- TRAP instruction
521
                CPU_INDSTACK, CPU_INDSTACK2,    -- indirect stacking
522
                CPU_STACK, CPU_STACK1,                  -- stacking operations
523 2 fabiop
                CPU_STACK2, CPU_STACK3,
524 3 fabiop
                CPU_UNSTACK, CPU_UNSTACK2,              -- unstacking operations
525
                CPU_UNSTACK3,
526 2 fabiop
                CPU_STORE,                                              -- store results, no change to the flags
527 3 fabiop
                CPU_VECTOR, CPU_VECTOR2,                -- vectoring stages
528
                CPU_RESET,                                              -- reset state
529
                CPU_ILLEGAL                                             -- illegal state
530 2 fabiop
        );
531
        type Tfetch_state is (
532
                F_ADDR,         -- instruction queue is initializing, reset pointers and empty queue
533
                F_READ          -- instruction queue is fetching opcodes
534
        );
535
        type Tdbg_uartrxstate is (
536
                DBGST_NOSYNC,                   -- debug UART receiver is not synchronized to the host
537
                DBGST_WAITSTART,                -- debug UART receiver is waiting for a 0x80 char
538
                DBGST_MEASURING,                -- debug UART receiver is measuring a possible sync char
539
                DBGST_IDLE,                             -- debug UART receiver is synchronized and awaiting commands
540
                DBGST_START,                    -- debug UART received a start bit
541
                DBGST_RECEIVING,                -- debug UART is receiving new command/data
542
                DBGST_ERROR                             -- debug UART receiver is in error state
543
        );
544
        type Tdbg_uarttxstate is (
545
                DBGTX_INIT,                             -- debug UART transmitter is initializing
546
                DBGTX_IDLE,                             -- debug UART transmitter is waiting new data to transmit
547
                DBGTX_START,                    -- debug UART transmitter is sending a start bit
548
                DBGTX_TRASMITTING,              -- debug UART transmitter is sending data
549
                DBGTX_BREAK,                    -- debug UART transmitter is preparing to send a break
550
                DBGTX_BREAK2                    -- debug UART is waiting for the break complete
551
        );
552
        type Tdbg_command is (
553
                DBG_WAIT_CMD,                                                   -- debugger is waiting for commands
554
                DBG_SEND_REV, DBG_SEND_REV2,                    -- debugger is processing a read revision command
555
                DBG_SEND_STATUS,                                                -- debugger is processing a read OCDST command
556
                DBG_WRITE_CTRL,                                                 -- debugger is processing a write OCDCTRL command
557
                DBG_SEND_CTRL,                                                  -- debugger is processing a read OCDCTRL command
558
                DBG_WRITE_PC, DBG_WRITE_PC2,                    -- debugger is processing a PC write command
559
                DBG_SEND_PC, DBG_SEND_PC2,                              -- debugger is processing a PC read command
560
                DBG_WRITE_REG, DBG_READ_REG,                    -- debugger is processing a read/write to registers
561
                DBG_REG, DBG_REG2, DBG_REG3,                    -- debugger is processing a read/write to registers
562
                DBG_REG4, DBG_REG5,                                             -- debugger is processing a read/write to registers
563
                DBG_WRITE_PROGMEM, DBG_READ_PROGMEM,    -- debugger is processing a read/write to program memory
564
                DBG_PROGMEM, DBG_PROGMEM2,                              -- debugger is processing a read/write to program memory
565
                DBG_PROGMEM3, DBG_PROGMEM4,                     -- debugger is processing a read/write to program memory
566
                DBG_PROGMEM5, DBG_PROGMEM6,                             -- debugger is processing a read/write to program memory
567
                DBG_STEP,                                                               -- debugger is processing a step command
568
                DBG_STUFF,                                                              -- debugger is processing a stuff command
569
                DBG_EXEC, DBG_EXEC2, DBG_EXEC3                  -- debugger is processing a execute command
570
        );
571
        type Tdbg_uart is record
572
                RX_STATE        : Tdbg_uartrxstate;
573
                TX_STATE        : Tdbg_uarttxstate;
574
                RX_DONE         : std_logic;                                            -- new data is available
575
                TX_EMPTY        : std_logic;                                            -- tx buffer is empty
576
                DBG_SYNC        : std_logic;                                            -- debugger is synchronized to host
577
                WRT                     : std_logic;                                            -- write/read command flag
578
                LAST_SMP        : std_logic;                                            -- last sample read from DBG_RX pin
579
                SIZE            : std_logic_vector(15 downto 0); -- 16-bit size of command
580
                TXSHIFTREG      : std_logic_vector(8 downto 0);          -- transmitter shift register
581
                RXSHIFTREG      : std_logic_vector(8 downto 0);          -- receiver shift register
582
                TX_DATA         : std_logic_vector(7 downto 0);          -- TX buffer
583
                RX_DATA         : std_logic_vector(7 downto 0);          -- RX buffer
584
                RXCNT           : integer range 0 to 15;                 -- received bit counter
585
                TXCNT           : integer range 0 to 15;                 -- transmitted bit counter
586
                BAUDPRE         : integer range 0 to 2;                          -- baud prescaler
587
                BAUDCNTRX       : std_logic_vector(11 downto 0); -- RX baud divider
588
                BAUDCNTTX       : std_logic_vector(11 downto 0); -- TX baud divider
589
                BITTIMERX       : std_logic_vector(11 downto 0); -- RX bit-time register (1/2 bit-time)
590
                BITTIMETX       : std_logic_vector(11 downto 0); -- TX bit-time register
591
        end record;
592
        variable CPU_STATE              : TCPU_STATE;                                           -- current CPU state 
593
        variable DBG_UART               : Tdbg_uart;
594
        variable DBG_CMD                : Tdbg_command;
595
        variable CAN_FETCH              : std_logic;                                            -- controls whether the instruction queue can actually fetch opcodes
596
        variable LU_INSTRUCTION : std_logic;                                            -- indicates a LU2-related instruction
597 3 fabiop
        variable INT_FLAG               : std_logic;                                            -- indicates an interrupt
598 2 fabiop
        variable WORD_DATA              : std_logic;                                            -- indicates a 16-bit data instruction
599 3 fabiop
        variable HALT                   : std_logic;                                            -- indicates the CPU is halted
600 2 fabiop
        variable PC                     : std_logic_vector(15 downto 0); -- program counter
601
        variable FETCH_ADDR             : std_logic_vector(15 downto 0); -- next address to be fetched
602
        variable DEST_ADDR16    : std_logic_vector(15 downto 0); -- temporary 16-bit destination address
603
        variable DEST_ADDR              : std_logic_vector(11 downto 0); -- temporary 12-bit destination address
604
        variable TEMP_DATA              : std_logic_vector(7 downto 0);          -- temporary 8-bit data
605 3 fabiop
        variable OLD_IRQ0               : std_logic_vector(7 downto 0);          -- previous state of IRQ inputs
606 2 fabiop
        variable INTVECT                : std_logic_vector(7 downto 0);          -- current interrupt vector (lower 8-bits)
607
        variable RESULT                 : std_logic_vector(7 downto 0);          -- temporary 8-bit result
608
        variable TEMP_OP                : std_logic_vector(3 downto 0);          -- ALU/LU2 operation code
609
        variable ATM_COUNTER    : integer range 0 to 3;                          -- temporary interrupt disable counter (ATM instruction)
610
        variable NUM_BYTES              : integer range 0 to 5;                          -- number of bytes decoded
611
        type Tinstructionqueue is record
612
                WRPOS                           : integer range 0 to 7;                          -- instruction queue write pointer
613
                RDPOS                           : integer range 0 to 7;                          -- instruction queue read pointer
614
                CNT                                     : integer range 0 to 7;                          -- instruction queue available bytes
615
                FETCH_STATE                     : tfetch_state;
616
                QUEUE                           : Tinstqueue;
617
                FULL                            : std_logic;                                            -- indicates whether the queue is full or not
618
        end record;
619
        variable IQUEUE                 : Tinstructionqueue;
620
        type Tocdcr is record
621
                DBGMODE                         : std_logic;
622
                BRKEN                           : std_logic;
623
                DBGACK                          : std_logic;
624
                BRKLOOP                         : std_logic;
625
                RST                                     : std_logic;
626
        end record;
627
        variable OCDCR                  : Tocdcr;
628
        type Tocdflags is record
629
                SINGLESTEP                      : std_logic;
630
        end record;
631
        variable OCD                    : Tocdflags;
632
 
633
        begin
634 3 fabiop
                RESET_OUT <= RESET or OCDCR.RST;
635
                if (RESET='1') then     -- reset operations             
636 2 fabiop
                        IAB <= x"0002";
637 3 fabiop
                        FRAB <= x"000";
638
                        IWDB <= x"00";
639 2 fabiop
                        SP := x"000";
640
                        RP := x"00";
641
                        WR <= '0';
642
                        PGM_WR <= '0';
643
                        STOP <= '0';
644
                        CAN_FETCH := '1';
645
                        FETCH_ADDR := x"0000";
646
                        DBG_UART.RX_STATE := DBGST_NOSYNC;
647
                        DBG_UART.TX_STATE := DBGTX_INIT;
648
                        OCDCR.DBGMODE := '0';
649
                        OCDCR.BRKEN := '0';
650
                        OCDCR.DBGACK := '0';
651
                        OCDCR.BRKLOOP := '0';
652
                        OCD.SINGLESTEP := '0';
653
                        OCDCR.RST := '0';
654
                        RXSYNC1 <= '1';
655
                        RXSYNC2 <= '1';
656
                        DBG_UART.LAST_SMP := '1';
657
                        IQUEUE.FETCH_STATE := F_ADDR;
658
                        IRQE := '0';
659
                        IRQ0 := x"00";
660
                        OLD_IRQ0 := x"00";
661
                        IRQ0ENH := x"00";
662
                        IRQ0ENL := x"00";
663
                        ATM_COUNTER := 0;
664
                        CPU_STATE := CPU_VECTOR;
665 3 fabiop
                elsif (rising_edge(CLK_OUT)) then
666
                        IRQ0_LATCH <= INT7&INT6&INT5&INT4&INT3&INT2&INT1&INT0;
667
                        if (OLD_IRQ0(0)/=IRQ0_LATCH(0)) then IRQ0(0) := '1'; end if;
668
                        if (OLD_IRQ0(1)/=IRQ0_LATCH(1)) then IRQ0(1) := '1'; end if;
669
                        if (OLD_IRQ0(2)/=IRQ0_LATCH(2)) then IRQ0(2) := '1'; end if;
670
                        if (OLD_IRQ0(3)/=IRQ0_LATCH(3)) then IRQ0(3) := '1'; end if;
671
                        if (OLD_IRQ0(4)/=IRQ0_LATCH(4)) then IRQ0(4) := '1'; end if;
672
                        if (OLD_IRQ0(5)/=IRQ0_LATCH(5)) then IRQ0(5) := '1'; end if;
673
                        if (OLD_IRQ0(6)/=IRQ0_LATCH(6)) then IRQ0(6) := '1'; end if;
674
                        if (OLD_IRQ0(7)/=IRQ0_LATCH(7)) then IRQ0(7) := '1'; end if;
675
                        OLD_IRQ0 := IRQ0_LATCH;
676
 
677
                        WR <= '0';
678
                        PGM_WR <= '0';
679
 
680
                        -- start of instruction queue FSM
681
                        if (CAN_FETCH='1') then
682
                                if (IQUEUE.FETCH_STATE=F_ADDR) then
683
                                        FETCH_ADDR := PC;
684
                                        IAB <= PC;
685
                                        IQUEUE.WRPOS := 0;
686
                                        IQUEUE.RDPOS := 0;
687
                                        IQUEUE.CNT := 0;
688
                                        IQUEUE.FETCH_STATE := F_READ;
689
                                else
690
                                        if (IQUEUE.FULL='0') then
691
                                                IQUEUE.QUEUE(IQUEUE.WRPOS) := IDB;
692
                                                FETCH_ADDR := FETCH_ADDR + 1;
693
                                                IAB <= FETCH_ADDR;
694
                                                IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
695
                                                IQUEUE.CNT := IQUEUE.CNT + 1;
696 2 fabiop
                                        end if;
697
                                end if;
698 3 fabiop
                        end if;
699
                        if (IQUEUE.CNT=7) then IQUEUE.FULL:='1'; else IQUEUE.FULL:='0';
700
                        end if;
701
                        -- end of instruction queue FSM 
702
 
703
                        -- start of debugger UART
704
                        DBG_UART.BAUDPRE := DBG_UART.BAUDPRE+1; -- baudrate prescaler
705
                        if (DBG_UART.BAUDPRE=0) then
706
                                DBG_UART.BAUDCNTRX := DBG_UART.BAUDCNTRX+1;
707
                                DBG_UART.BAUDCNTTX := DBG_UART.BAUDCNTTX+1;
708
                        end if;
709
                        RXSYNC2 <= DBG_RX;              -- DBG_RX input synchronization
710
                        RXSYNC1 <= RXSYNC2;             -- RXSYNC1 is a synchronized DBG_RX signal
711
                        case DBG_UART.RX_STATE is
712
                                when DBGST_NOSYNC =>
713
                                        DBG_UART.DBG_SYNC := '0';
714
                                        DBG_UART.RX_DONE := '0';
715
                                        DBG_CMD := DBG_WAIT_CMD;
716
                                        DBG_UART.RX_STATE := DBGST_WAITSTART;
717
                                when DBGST_WAITSTART =>
718
                                        if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then
719
                                                DBG_UART.RX_STATE := DBGST_MEASURING;
720
                                                DBG_UART.BAUDCNTRX := x"000";
721
                                        end if;
722
                                when DBGST_MEASURING =>
723
                                        if (DBG_UART.BAUDCNTRX/=x"FFF") then
724
                                                if (RXSYNC1='1') then
725
                                                        DBG_UART.DBG_SYNC := '1';
726
                                                        DBG_UART.RX_STATE := DBGST_IDLE;
727
                                                        DBG_UART.BITTIMERX := "0000"&DBG_UART.BAUDCNTRX(11 downto 4);
728
                                                        DBG_UART.BITTIMETX := "000"&DBG_UART.BAUDCNTRX(11 downto 3);
729 2 fabiop
                                                end if;
730 3 fabiop
                                        else
731
                                                DBG_UART.RX_STATE := DBGST_NOSYNC;
732
                                        end if;
733
                                when DBGST_IDLE =>
734
                                        DBG_UART.BAUDCNTRX:=x"000";
735
                                        DBG_UART.RXCNT:=0;
736
                                        if (RXSYNC1='0' and DBG_UART.LAST_SMP='1') then  -- it's a start bit
737
                                                DBG_UART.RX_STATE := DBGST_START;
738
                                        end if;
739
                                when DBGST_START =>
740
                                        if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMERX) then
741
                                                DBG_UART.BAUDCNTRX:=x"000";
742
                                                if (RXSYNC1='0') then
743
                                                        DBG_UART.RX_STATE := DBGST_RECEIVING;
744 2 fabiop
                                                else
745 3 fabiop
                                                        DBG_UART.RX_STATE := DBGST_ERROR;
746
                                                        DBG_UART.TX_STATE := DBGTX_BREAK;
747 2 fabiop
                                                end if;
748 3 fabiop
                                        end if;
749
                                when DBGST_RECEIVING =>
750
                                        if (DBG_UART.BAUDCNTRX=DBG_UART.BITTIMETX) then
751 2 fabiop
                                                DBG_UART.BAUDCNTRX:=x"000";
752 3 fabiop
                                                -- one bit time elapsed, sample RX input
753
                                                DBG_UART.RXSHIFTREG := RXSYNC1 & DBG_UART.RXSHIFTREG(8 downto 1);
754
                                                DBG_UART.RXCNT := DBG_UART.RXCNT + 1;
755
                                                if (DBG_UART.RXCNT=9) then
756
                                                        if (RXSYNC1='1') then
757
                                                                -- if the stop bit is 1, rx is completed ok
758
                                                                DBG_UART.RX_DATA := DBG_UART.RXSHIFTREG(7 downto 0);
759
                                                                DBG_UART.RX_DONE := '1';
760
                                                                DBG_UART.RX_STATE := DBGST_IDLE;
761 2 fabiop
                                                        else
762 3 fabiop
                                                                -- if the stop bit is 0, it is a break char, reset receiver
763 2 fabiop
                                                                DBG_UART.RX_STATE := DBGST_ERROR;
764
                                                                DBG_UART.TX_STATE := DBGTX_BREAK;
765
                                                        end if;
766
                                                end if;
767 3 fabiop
                                        end if;
768
                                when others =>
769
                        end case;
770
                        DBG_UART.LAST_SMP := RXSYNC1;
771
                        case DBG_UART.TX_STATE is
772
                                when DBGTX_INIT =>
773
                                        DBG_UART.TX_EMPTY := '1';
774
                                        DBG_UART.TX_STATE:=DBGTX_IDLE;
775
                                when DBGTX_IDLE =>      -- UART is idle and not transmitting
776
                                        DBG_TX <= '1';
777
                                        if (DBG_UART.TX_EMPTY='0' and DBG_UART.DBG_SYNC='1') then        -- there is new data in TX_DATA register
778 2 fabiop
                                                DBG_UART.BAUDCNTTX:=x"000";
779 3 fabiop
                                                DBG_UART.TX_STATE := DBGTX_START;
780
                                        end if;
781
                                when DBGTX_START =>
782
                                        if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
783
                                                DBG_UART.BAUDCNTTX:=x"000";
784
                                                DBG_UART.TXSHIFTREG := '1'&DBG_UART.TX_DATA;
785
                                                DBG_UART.TXCNT := 10;
786
                                                DBG_UART.TX_STATE := DBGTX_TRASMITTING;
787 2 fabiop
                                                DBG_TX <= '0';
788 3 fabiop
                                        end if;
789
                                when DBGTX_TRASMITTING =>       -- UART is shifting data
790
                                        if (DBG_UART.BAUDCNTTX=DBG_UART.BITTIMETX) then
791
                                                DBG_UART.BAUDCNTTX:=x"000";
792
                                                DBG_TX <= DBG_UART.TXSHIFTREG(0);
793
                                                DBG_UART.TXSHIFTREG := '1'&DBG_UART.TXSHIFTREG(8 downto 1);
794
                                                DBG_UART.TXCNT :=DBG_UART.TXCNT - 1;
795
                                                if (DBG_UART.TXCNT=0) then
796
                                                        DBG_UART.TX_STATE:=DBGTX_IDLE;
797
                                                        DBG_UART.TX_EMPTY := '1';
798 2 fabiop
                                                end if;
799 3 fabiop
                                        end if;
800
                                when DBGTX_BREAK =>
801
                                        DBG_UART.BAUDCNTTX:=x"000";
802
                                        DBG_UART.TX_STATE:=DBGTX_BREAK2;
803
                                when DBGTX_BREAK2 =>
804
                                        DBG_TX <= '0';
805
                                        DBG_UART.RX_STATE := DBGST_NOSYNC;
806
                                        if (DBG_UART.BAUDCNTTX=x"FFF") then
807
                                                DBG_UART.TX_STATE:=DBGTX_INIT;
808
                                        end if;
809
                        end case;
810
                        if (RXSYNC1='0') then DBG_TX <='0';       -- this mimics open-collector feature of OCD communication
811
                        end if;
812
                        -- end of the debugger UART             
813
 
814
                        -- This is the instruction decoder
815
                        case CPU_STATE IS
816
                                when CPU_DECOD =>
817
                                        TEMP_OP := ALU_LD;                                      -- default ALU operation is load
818
                                        LU_INSTRUCTION := '0';                           -- default is ALU operation (instead of LU2)
819
                                        INT_FLAG := '0';                                 -- reset temporary interrupt flag
820
                                        WORD_DATA := '0';                                        -- default is 8-bit operation
821
                                        INTVECT := x"00";                                       -- default vector is 0x00
822
                                        NUM_BYTES := 0;                                          -- default instruction length is 0 bytes
823
 
824
                                        -- start of debugger command processor
825
                                        case DBG_CMD is
826
                                                when DBG_WAIT_CMD =>
827
                                                        if (DBG_UART.RX_DONE='1') then
828
                                                                case DBG_UART.RX_DATA is
829
                                                                        when DBGCMD_READ_REV =>         DBG_CMD := DBG_SEND_REV;
830
                                                                        when DBGCMD_READ_STATUS =>      DBG_CMD := DBG_SEND_STATUS;
831
                                                                        when DBGCMD_WRITE_CTRL =>       DBG_CMD := DBG_WRITE_CTRL;
832
                                                                        when DBGCMD_READ_CTRL =>        DBG_CMD := DBG_SEND_CTRL;
833
                                                                        when DBGCMD_WRITE_PC =>         DBG_CMD := DBG_WRITE_PC;
834
                                                                        when DBGCMD_READ_PC =>          DBG_CMD := DBG_SEND_PC;
835
                                                                        when DBGCMD_WRITE_REG =>        DBG_CMD := DBG_WRITE_REG;
836
                                                                        when DBGCMD_READ_REG =>         DBG_CMD := DBG_READ_REG;
837
                                                                        when DBGCMD_WRITE_PROGRAM=>     DBG_CMD := DBG_WRITE_PROGMEM;
838
                                                                        when DBGCMD_READ_PROGRAM=>      DBG_CMD := DBG_READ_PROGMEM;
839
                                                                        when DBGCMD_STEP =>                     DBG_CMD := DBG_STEP;
840
                                                                        when DBGCMD_STUFF =>            DBG_CMD := DBG_STUFF;
841
                                                                        when DBGCMD_EXEC =>                     DBG_CMD := DBG_EXEC;
842
                                                                        when others =>
843
                                                                end case;
844
                                                                DBG_UART.RX_DONE:='0';
845 2 fabiop
                                                        end if;
846 3 fabiop
                                                when DBG_SEND_REV =>    -- read revision first byte
847
                                                        if (DBG_UART.TX_EMPTY='1') then
848
                                                                DBG_UART.TX_DATA:=x"01";
849
                                                                DBG_UART.TX_EMPTY:='0';
850
                                                                DBG_CMD := DBG_SEND_REV2;
851
                                                        end if;
852
                                                when DBG_SEND_REV2 =>   -- read revision second byte
853
                                                        if (DBG_UART.TX_EMPTY='1') then
854
                                                                DBG_UART.TX_DATA:=x"00";
855
                                                                DBG_UART.TX_EMPTY:='0';
856
                                                                DBG_CMD := DBG_WAIT_CMD;
857
                                                        end if;
858
                                                when DBG_SEND_STATUS => -- read OCD status
859
                                                        if (DBG_UART.TX_EMPTY='1') then
860
                                                                DBG_UART.TX_DATA:=OCDCR.DBGMODE&HALT&"000000";
861
                                                                DBG_UART.TX_EMPTY:='0';
862
                                                                DBG_CMD := DBG_WAIT_CMD;
863
                                                        end if;
864
                                                when DBG_WRITE_CTRL =>  -- write OCD control register
865
                                                        if (DBG_UART.RX_DONE='1') then
866
                                                                DBG_UART.RX_DONE:='0';
867
                                                                OCDCR.DBGMODE := DBG_UART.RX_DATA(7);
868
                                                                OCDCR.BRKEN := DBG_UART.RX_DATA(6);
869
                                                                OCDCR.DBGACK := DBG_UART.RX_DATA(5);
870
                                                                OCDCR.BRKLOOP := DBG_UART.RX_DATA(4);
871
                                                                OCDCR.RST := DBG_UART.RX_DATA(0);
872
                                                                if (OCDCR.RST='1') then CPU_STATE:=CPU_RESET;
873
                                                                end if;
874
                                                                DBG_CMD := DBG_WAIT_CMD;
875
                                                        end if;
876
                                                when DBG_SEND_CTRL =>   -- read OCD control register
877
                                                        if (DBG_UART.TX_EMPTY='1') then
878
                                                                DBG_UART.TX_DATA:=OCDCR.DBGMODE&OCDCR.BRKEN&OCDCR.DBGACK&OCDCR.BRKLOOP&"000"&OCDCR.RST;
879
                                                                DBG_UART.TX_EMPTY:='0';
880
                                                                DBG_CMD := DBG_WAIT_CMD;
881
                                                        end if;
882
                                                when DBG_WRITE_PC =>    -- write PC high byte
883
                                                        if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
884
                                                                DBG_UART.RX_DONE:='0';
885
                                                                CAN_FETCH := '0';
886
                                                                PC(15 downto 8) := DBG_UART.RX_DATA;
887
                                                                DBG_CMD := DBG_WRITE_PC2;
888
                                                        end if;
889
                                                when DBG_WRITE_PC2 =>   -- write PC low byte
890
                                                        if (DBG_UART.RX_DONE='1') then
891
                                                                DBG_UART.RX_DONE:='0';
892
                                                                PC(7 downto 0) := DBG_UART.RX_DATA;
893
                                                                IQUEUE.FETCH_STATE := F_ADDR;
894
                                                                IQUEUE.CNT := 0;
895
                                                                CAN_FETCH := '1';
896
                                                                DBG_CMD := DBG_WAIT_CMD;
897
                                                        end if;
898
                                                when DBG_SEND_PC =>             -- read PC high byte
899
                                                        if (DBG_UART.TX_EMPTY='1') then
900
                                                                DBG_UART.TX_DATA:=PC(15 downto 8);
901
                                                                DBG_UART.TX_EMPTY:='0';
902
                                                                DBG_CMD := DBG_SEND_PC2;
903
                                                        end if;
904
                                                when DBG_SEND_PC2 =>    -- read PC high byte
905
                                                        if (DBG_UART.TX_EMPTY='1') then
906
                                                                DBG_UART.TX_DATA:=PC(7 downto 0);
907
                                                                DBG_UART.TX_EMPTY:='0';
908
                                                                DBG_CMD := DBG_WAIT_CMD;
909
                                                        end if;
910
                                                when DBG_WRITE_REG =>   -- write to SFR/user registers
911
                                                        DBG_UART.WRT := '1';
912
                                                        DBG_CMD := DBG_REG;
913
                                                when DBG_READ_REG =>    -- read SFR/user registers
914
                                                        DBG_UART.WRT := '0';
915
                                                        DBG_CMD := DBG_REG;
916
                                                when DBG_REG =>                 -- proceed with register read/write
917
                                                        if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
918
                                                                FRAB(11 downto 8) <= DBG_UART.RX_DATA(3 downto 0);
919
                                                                DBG_UART.RX_DONE:='0';
920
                                                                DBG_CMD := DBG_REG2;
921
                                                        end if;
922
                                                when DBG_REG2 =>
923
                                                        if (DBG_UART.RX_DONE='1') then
924
                                                                FRAB(7 downto 0) <= DBG_UART.RX_DATA;
925
                                                                DBG_UART.RX_DONE:='0';
926
                                                                DBG_CMD := DBG_REG3;
927
                                                        end if;
928
                                                when DBG_REG3 =>
929
                                                        if (DBG_UART.RX_DONE='1') then
930
                                                                DBG_UART.SIZE := x"00"&DBG_UART.RX_DATA;
931
                                                                DBG_UART.RX_DONE:='0';
932
                                                                DBG_CMD := DBG_REG4;
933
                                                        end if;
934
                                                when DBG_REG4 =>
935 2 fabiop
                                                        if (DBG_UART.WRT='1') then
936
                                                                if (DBG_UART.RX_DONE='1') then
937
                                                                        CPU_STATE := CPU_OMA;
938
                                                                        TEMP_DATA := DBG_UART.RX_DATA;
939
                                                                        DBG_UART.RX_DONE:='0';
940
                                                                        DBG_CMD := DBG_REG5;
941
                                                                end if;
942
                                                        else
943
                                                                if (DBG_UART.TX_EMPTY='1') then
944 3 fabiop
                                                                        DBG_UART.TX_DATA:=DATAREAD(FRAB);
945 2 fabiop
                                                                        DBG_UART.TX_EMPTY:='0';
946
                                                                        DBG_CMD := DBG_REG5;
947
                                                                end if;
948
                                                        end if;
949 3 fabiop
                                                when DBG_REG5 =>
950
                                                        FRAB <= FRAB + 1;
951 2 fabiop
                                                        DBG_UART.SIZE := DBG_UART.SIZE - 1;
952
                                                        if (DBG_UART.SIZE=x"0000") then
953
                                                                DBG_CMD := DBG_WAIT_CMD;
954
                                                        else DBG_CMD := DBG_REG4;
955
                                                        end if;
956 3 fabiop
                                                when DBG_WRITE_PROGMEM =>
957
                                                        DBG_UART.WRT := '1';
958
                                                        DBG_CMD := DBG_PROGMEM;
959
                                                when DBG_READ_PROGMEM =>
960
                                                        DBG_UART.WRT := '0';
961
                                                        DBG_CMD := DBG_PROGMEM;
962
                                                when DBG_PROGMEM =>
963 2 fabiop
                                                        if (DBG_UART.RX_DONE='1') then
964 3 fabiop
                                                                CAN_FETCH := '0';
965
                                                                IAB(15 downto 8) <= DBG_UART.RX_DATA;
966 2 fabiop
                                                                DBG_UART.RX_DONE:='0';
967 3 fabiop
                                                                DBG_CMD := DBG_PROGMEM2;
968 2 fabiop
                                                        end if;
969 3 fabiop
                                                when DBG_PROGMEM2 =>
970
                                                        if (DBG_UART.RX_DONE='1') then
971
                                                                IAB(7 downto 0) <= DBG_UART.RX_DATA;
972
                                                                DBG_UART.RX_DONE:='0';
973
                                                                DBG_CMD := DBG_PROGMEM3;
974
                                                        end if;
975
                                                when DBG_PROGMEM3 =>
976
                                                        if (DBG_UART.RX_DONE='1') then
977
                                                                DBG_UART.SIZE(15 downto 8) := DBG_UART.RX_DATA;
978
                                                                DBG_UART.RX_DONE:='0';
979
                                                                DBG_CMD := DBG_PROGMEM4;
980
                                                        end if;
981
                                                when DBG_PROGMEM4 =>
982
                                                        if (DBG_UART.RX_DONE='1') then
983
                                                                DBG_UART.SIZE(7 downto 0) := DBG_UART.RX_DATA;
984
                                                                DBG_UART.RX_DONE:='0';
985
                                                                DBG_CMD := DBG_PROGMEM5;
986 2 fabiop
                                                        end if;
987 3 fabiop
                                                when DBG_PROGMEM5 =>
988
                                                        if (DBG_UART.WRT='1') then
989
                                                                if (DBG_UART.RX_DONE='1') then
990
                                                                        IWDB <= DBG_UART.RX_DATA;
991
                                                                        DBG_UART.RX_DONE:='0';
992
                                                                        PGM_WR <= '1';
993
                                                                        DBG_CMD := DBG_PROGMEM6;
994
                                                                end if;
995
                                                        else
996
                                                                if (DBG_UART.TX_EMPTY='1') then
997
                                                                        DBG_UART.TX_DATA:=IDB;
998
                                                                        DBG_UART.TX_EMPTY:='0';
999
                                                                        DBG_CMD := DBG_PROGMEM6;
1000
                                                                end if;
1001
                                                        end if;
1002
                                                when DBG_PROGMEM6 =>
1003
                                                        IAB <= IAB + 1;
1004
                                                        DBG_UART.SIZE := DBG_UART.SIZE - 1;
1005
                                                        if (DBG_UART.SIZE=x"0000") then
1006
                                                                DBG_CMD := DBG_WAIT_CMD;
1007
                                                                CAN_FETCH := '1';
1008
                                                                IQUEUE.CNT := 0;
1009
                                                                IQUEUE.FETCH_STATE := F_ADDR;
1010
                                                        else DBG_CMD := DBG_PROGMEM5;
1011
                                                        end if;
1012
                                                when DBG_STEP =>
1013 2 fabiop
                                                        OCD.SINGLESTEP:='1';
1014
                                                        IQUEUE.FETCH_STATE := F_ADDR;
1015 3 fabiop
                                                        DBG_CMD := DBG_WAIT_CMD;
1016
                                                when DBG_STUFF =>
1017
                                                        if (DBG_UART.RX_DONE='1' and OCDCR.DBGMODE='1') then
1018
                                                                IQUEUE.QUEUE(IQUEUE.RDPOS) := DBG_UART.RX_DATA;
1019 2 fabiop
                                                                DBG_UART.RX_DONE:='0';
1020 3 fabiop
                                                                DBG_CMD := DBG_STEP;
1021 2 fabiop
                                                        end if;
1022 3 fabiop
                                                when DBG_EXEC =>
1023
                                                        if (OCDCR.DBGMODE='1') then
1024
                                                                OCD.SINGLESTEP:='1';
1025
                                                                CAN_FETCH:='0';
1026
                                                                IQUEUE.CNT := 0;
1027
                                                                IQUEUE.FETCH_STATE := F_ADDR;
1028
                                                        end if;
1029
                                                        DBG_CMD := DBG_EXEC2;
1030
                                                when DBG_EXEC2 =>
1031
                                                        if (DBG_UART.RX_DONE='1') then
1032
                                                                if (OCDCR.DBGMODE='0') then DBG_CMD := DBG_WAIT_CMD;
1033
                                                                else
1034
                                                                        IQUEUE.QUEUE(IQUEUE.WRPOS) := DBG_UART.RX_DATA;
1035
                                                                        DBG_UART.RX_DONE:='0';
1036
                                                                        IQUEUE.WRPOS := IQUEUE.WRPOS + 1;
1037
                                                                        IQUEUE.CNT := IQUEUE.CNT + 1;
1038
                                                                        DBG_CMD := DBG_EXEC3;
1039
                                                                end if;
1040
                                                        end if;
1041
                                                when DBG_EXEC3 =>
1042
                                                        if (OCD.SINGLESTEP='1') then DBG_CMD := DBG_EXEC2; else
1043
                                                                DBG_CMD := DBG_WAIT_CMD;
1044
                                                                IQUEUE.FETCH_STATE := F_ADDR;
1045
                                                        end if;
1046
                                                when others =>
1047
                                        end case;
1048
                                        -- end of debugger command processor
1049
 
1050 2 fabiop
                                        if (ATM_COUNTER/=3) then ATM_COUNTER := ATM_COUNTER+1;
1051
                                        else    -- interrupt processing *****************************************************************************
1052
                                                if (IRQE='1') then      -- if interrupts are enabled
1053 3 fabiop
                                                        -- first the highest priority level interrupts
1054 2 fabiop
                                                        if ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='1') then
1055
                                                                INTVECT:=x"08";
1056
                                                                IRQ0(7):='0';
1057
                                                        elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='1') then
1058
                                                                INTVECT:=x"0A";
1059
                                                                IRQ0(6):='0';
1060
                                                        elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='1') then
1061
                                                                INTVECT:=x"0C";
1062
                                                                IRQ0(5):='0';
1063
                                                        elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='1') then
1064
                                                                INTVECT:=x"0E";
1065
                                                                IRQ0(4):='0';
1066
                                                        elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='1') then
1067
                                                                INTVECT:=x"10";
1068
                                                                IRQ0(3):='0';
1069
                                                        elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='1') then
1070
                                                                INTVECT:=x"12";
1071
                                                                IRQ0(2):='0';
1072
                                                        elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='1') then
1073
                                                                INTVECT:=x"14";
1074
                                                                IRQ0(1):='0';
1075
                                                        elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='1') then
1076
                                                                INTVECT:=x"16";
1077
                                                                IRQ0(0):='0';
1078
                                                        -- now priority level 2 interrupts
1079
                                                        elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='1') and IRQ0ENL(7)='0') then
1080
                                                                INTVECT:=x"08";
1081
                                                                IRQ0(7):='0';
1082
                                                        elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='1') and IRQ0ENL(6)='0') then
1083
                                                                INTVECT:=x"0A";
1084
                                                                IRQ0(6):='0';
1085
                                                        elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='1') and IRQ0ENL(5)='0') then
1086
                                                                INTVECT:=x"0C";
1087
                                                                IRQ0(5):='0';
1088
                                                        elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='1') and IRQ0ENL(4)='0') then
1089
                                                                INTVECT:=x"0E";
1090
                                                                IRQ0(4):='0';
1091
                                                        elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='1') and IRQ0ENL(3)='0') then
1092
                                                                INTVECT:=x"10";
1093
                                                                IRQ0(3):='0';
1094
                                                        elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='1') and IRQ0ENL(2)='0') then
1095
                                                                INTVECT:=x"12";
1096
                                                                IRQ0(2):='0';
1097
                                                        elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='1') and IRQ0ENL(1)='0') then
1098
                                                                INTVECT:=x"14";
1099
                                                                IRQ0(1):='0';
1100
                                                        elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='1') and IRQ0ENL(0)='0') then
1101
                                                                INTVECT:=x"16";
1102
                                                                IRQ0(0):='0';
1103
                                                        -- now priority level 1 interrupts
1104
                                                        elsif ((IRQ0(7)='1') and (IRQ0ENH(7)='0') and IRQ0ENL(7)='1') then
1105
                                                                INTVECT:=x"08";
1106
                                                                IRQ0(7):='0';
1107
                                                        elsif ((IRQ0(6)='1') and (IRQ0ENH(6)='0') and IRQ0ENL(6)='1') then
1108
                                                                INTVECT:=x"0A";
1109
                                                                IRQ0(6):='0';
1110
                                                        elsif ((IRQ0(5)='1') and (IRQ0ENH(5)='0') and IRQ0ENL(5)='1') then
1111
                                                                INTVECT:=x"0C";
1112
                                                                IRQ0(5):='0';
1113
                                                        elsif ((IRQ0(4)='1') and (IRQ0ENH(4)='0') and IRQ0ENL(4)='1') then
1114
                                                                INTVECT:=x"0E";
1115
                                                                IRQ0(4):='0';
1116
                                                        elsif ((IRQ0(3)='1') and (IRQ0ENH(3)='0') and IRQ0ENL(3)='1') then
1117
                                                                INTVECT:=x"10";
1118
                                                                IRQ0(3):='0';
1119
                                                        elsif ((IRQ0(2)='1') and (IRQ0ENH(2)='0') and IRQ0ENL(2)='1') then
1120
                                                                INTVECT:=x"12";
1121
                                                                IRQ0(2):='0';
1122
                                                        elsif ((IRQ0(1)='1') and (IRQ0ENH(1)='0') and IRQ0ENL(1)='1') then
1123
                                                                INTVECT:=x"14";
1124
                                                                IRQ0(1):='0';
1125
                                                        elsif ((IRQ0(0)='1') and (IRQ0ENH(0)='0') and IRQ0ENL(0)='1') then
1126
                                                                INTVECT:=x"16";
1127
                                                                IRQ0(0):='0';
1128
                                                        end if;
1129
                                                        if (INTVECT/=x"00") then
1130 3 fabiop
                                                                if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
1131
                                                                        DEST_ADDR16 := PC;
1132
                                                                        IAB <= x"00"&INTVECT;   -- build the interrupt vector address
1133
                                                                        SP := SP - 1;                   -- prepare stack pointer by decrementing it
1134
                                                                        FRAB <= SP;                             -- put SP on FRAB
1135
                                                                        CAN_FETCH := '0';                -- disable instruction fetching
1136
                                                                        OCD.SINGLESTEP := '0';   -- disable stepping
1137
                                                                        IQUEUE.CNT := 0;         -- set queue empty
1138
                                                                        STOP <= '0';                     -- disable stop bit
1139
                                                                        HALT := '0';                     -- disable halt mode
1140
                                                                        INT_FLAG := '1';                -- signal it is an interrupt stacking operation
1141
                                                                        CPU_STATE := CPU_VECTOR;
1142
                                                                end if;
1143 2 fabiop
                                                        end if;
1144 3 fabiop
                                                end if; -- if IRQE=1
1145
                                        end if; -- if ATM_COUNTER...
1146
                                        if (STOP='0' and HALT='0') then
1147
                                                if (OCDCR.DBGMODE='0' or (OCDCR.DBGMODE='1' and OCD.SINGLESTEP='1')) then
1148
                                                        ------------------------------------------------------------------------------------------------------------------------------
1149
                                                        --**************************************************************************************************************************--
1150
                                                        --                                                     5-byte instructions                                                  --
1151
                                                        --**************************************************************************************************************************--
1152
                                                        ------------------------------------------------------------------------------------------------------------------------------
1153
                                                        if (IQUEUE.CNT>=5) then -- 5-byte instructions
1154
                                                                ---------------------------------------------------------------------------------------------------- 2nd page instructions
1155
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
1156
                                                                        ---------------------------------------------------------------------------------------------- CPC ER2,ER1 instruction
1157
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A8") then
1158
                                                                                FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
1159
                                                                                DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
1160
                                                                                TEMP_OP := ALU_CPC;
1161
                                                                                NUM_BYTES := 5;
1162
                                                                                CPU_STATE := CPU_TMA;
1163
                                                                        ---------------------------------------------------------------------------------------------- CPC IMM,ER1 instruction
1164
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A9") then
1165
                                                                                FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
1166
                                                                                TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1167
                                                                                TEMP_OP := ALU_CPC;
1168
                                                                                NUM_BYTES := 5;
1169
                                                                                CPU_STATE := CPU_OMA;
1170
                                                                        --------------------------------------------------------------------------------------------- LDWX ER1,ER2 instruction
1171
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"E8") then
1172
                                                                                FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3)(7 downto 4));
1173
                                                                                DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+3)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+4));
1174
                                                                                NUM_BYTES := 5;
1175
                                                                                CPU_STATE := CPU_LDW;
1176
                                                                        end if;
1177 2 fabiop
                                                                end if;
1178
                                                        end if;
1179 3 fabiop
 
1180
                                                        ------------------------------------------------------------------------------------------------------------------------------
1181
                                                        --**************************************************************************************************************************--
1182
                                                        --                                                     4-byte instructions                                                  --
1183
                                                        --**************************************************************************************************************************--
1184
                                                        ------------------------------------------------------------------------------------------------------------------------------
1185
                                                        if (IQUEUE.CNT>=4) then -- 4-byte instructions
1186
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then    ------------------------------------------------ column 9 instructions
1187
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1188
                                                                                when x"8" =>    ------------------------------------------------------------------------- LDX rr1,r2,X instruction
1189
                                                                                when x"9" =>    ------------------------------------------------------------------------ LEA rr1,rr2,X instruction
1190
                                                                                when x"C" =>
1191
                                                                                        CPU_STATE := CPU_ILLEGAL;
1192
                                                                                when x"D" =>
1193
                                                                                        CPU_STATE := CPU_ILLEGAL;
1194
                                                                                when x"F" =>
1195
                                                                                        CPU_STATE := CPU_ILLEGAL;
1196
                                                                                when others =>  -------------------------------------------------------------- IM,ER1 addressing mode instructions
1197
                                                                                        FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
1198
                                                                                        TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
1199
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1200
                                                                                        NUM_BYTES := 4;
1201
                                                                                        CPU_STATE := CPU_OMA;
1202
                                                                        end case;
1203
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
1204
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1205
                                                                                when x"8" =>    ------------------------------------------------------------------------- LDX r1,rr2,X instruction
1206
                                                                                when x"9" =>    -------------------------------------------------------------------------- LEA r1,r2,X instruction
1207
                                                                                when x"C" =>    -------------------------------------------------------------------------------- PUSHX instruction
1208
                                                                                when x"D" =>    --------------------------------------------------------------------------------- POPX instruction
1209
                                                                                when x"F" =>
1210
                                                                                        CPU_STATE := CPU_ILLEGAL;
1211
                                                                                when others =>  ------------------------------------------------------------- ER2,ER1 addressing mode instructions
1212
                                                                                        FRAB <= ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+1)) & IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
1213
                                                                                        DEST_ADDR := ADDRESSER12((IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0)) & IQUEUE.QUEUE(IQUEUE.RDPOS+3));
1214
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1215
                                                                                        NUM_BYTES := 4;
1216
                                                                                        CPU_STATE := CPU_TMA;
1217
                                                                        end case;
1218
                                                                ---------------------------------------------------------------------------------------------------- 2nd page instructions
1219
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
1220
                                                                        ------------------------------------------------------------------------------------------------ CPC R2,R1 instruction
1221
                                                                        TEMP_OP := ALU_CPC;
1222
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A4") then
1223
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
1224
                                                                                DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1225 2 fabiop
                                                                                NUM_BYTES := 4;
1226 3 fabiop
                                                                                CPU_STATE := CPU_TMA;
1227
                                                                        ----------------------------------------------------------------------------------------------- CPC IR2,R1 instruction
1228
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A5") then
1229
                                                                                DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+3));
1230
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1231 2 fabiop
                                                                                NUM_BYTES := 4;
1232 3 fabiop
                                                                                CPU_STATE := CPU_ISMD1;
1233
                                                                        ----------------------------------------------------------------------------------------------- CPC R1,IMM instruction
1234
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A6") then
1235
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1236
                                                                                TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
1237
                                                                                NUM_BYTES := 4;
1238
                                                                                CPU_STATE := CPU_OMA;
1239
                                                                        ---------------------------------------------------------------------------------------------- CPC IR1,IMM instruction
1240
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A7") then
1241
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1242
                                                                                TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+3);
1243
                                                                                NUM_BYTES := 4;
1244
                                                                                CPU_STATE := CPU_IND1;
1245
                                                                        end if;
1246 2 fabiop
                                                                end if;
1247
                                                        end if;
1248 3 fabiop
 
1249
                                                        ------------------------------------------------------------------------------------------------------------------------------
1250
                                                        --**************************************************************************************************************************--
1251
                                                        --                                                     3-byte instructions                                                  --
1252
                                                        --**************************************************************************************************************************--
1253
                                                        ------------------------------------------------------------------------------------------------------------------------------
1254
                                                        if (IQUEUE.CNT>=3) then -- 3-byte instructions
1255
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"D") then    -------------------------------------------------- JP cc,DirectAddress
1256
                                                                        if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
1257
                                                                                PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1258
                                                                                IQUEUE.FETCH_STATE := F_ADDR;
1259
                                                                        else
1260 2 fabiop
                                                                                NUM_BYTES := 3;
1261 3 fabiop
                                                                        end if;
1262
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"9") then -------------------------------------------- column 9 instructions
1263
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then   ----------------------------------------- LDX rr1,r2,X instruction
1264
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1265
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1266
                                                                                RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);                                                                                                 -- RESULT = offset (X)
1267 2 fabiop
                                                                                NUM_BYTES := 3;
1268 3 fabiop
                                                                                CPU_STATE := CPU_XRRD;
1269
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then        ------------------------------------ LEA rr1,rr2,X instruction
1270
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1271 2 fabiop
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1272 3 fabiop
                                                                                RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1273
                                                                                NUM_BYTES := 3;
1274
                                                                                CPU_STATE := CPU_XRRTORR;
1275
                                                                        end if;
1276
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"8") then -------------------------------------------- column 8 instructions
1277
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"8") then   ----------------------------------------- LDX r1,rr2,X instruction
1278
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1279
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1280 2 fabiop
                                                                                RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);                                                                                                 -- RESULT = offset (X)
1281
                                                                                NUM_BYTES := 3;
1282 3 fabiop
                                                                                CPU_STATE := CPU_XRRS;
1283
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"9") then        -------------------------------------- LEA r1,r2,X instruction
1284
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1285
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1286 2 fabiop
                                                                                RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1287
                                                                                NUM_BYTES := 3;
1288 3 fabiop
                                                                                CPU_STATE := CPU_XRTOM;
1289
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"C") then        ---------------------------------------- PUSHX ER2 instruction
1290
                                                                                SP := SP - 1;
1291
                                                                                FRAB <= ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
1292
                                                                                DEST_ADDR := SP;
1293 2 fabiop
                                                                                NUM_BYTES := 3;
1294 3 fabiop
                                                                                CPU_STATE := CPU_TMA;
1295
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)=x"D") then        ----------------------------------------- POPX ER2 instruction
1296
                                                                                FRAB <= SP;
1297
                                                                                DEST_ADDR := ADDRESSER12(IQUEUE.QUEUE(IQUEUE.RDPOS+1)&IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));
1298
                                                                                SP := SP + 1;
1299 2 fabiop
                                                                                NUM_BYTES := 3;
1300 3 fabiop
                                                                                CPU_STATE := CPU_TMA;
1301
                                                                        end if;
1302
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"7") then -------------------------------------------- column 7 instructions
1303
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1304
                                                                                when x"8" =>    ------------------------------------------------------------------------- LDX IRR2,IR1 instruction
1305
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1306
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1307
                                                                                        NUM_BYTES := 3;
1308
                                                                                        CPU_STATE := CPU_IRRS;
1309
                                                                                when x"9" =>    ------------------------------------------------------------------------- LDX IR2,IRR1 instruction
1310
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1311
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1312
                                                                                        NUM_BYTES := 3;
1313
                                                                                        CPU_STATE := CPU_IMTOIRR;
1314
                                                                                when x"C" =>    --------------------------------------------------------------------------- LD r1,r2,X instruction
1315
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1316
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1317
                                                                                        RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);                                                                                                 -- RESULT = offset (X)
1318
                                                                                        NUM_BYTES := 3;
1319
                                                                                        CPU_STATE := CPU_XADTOM;
1320
                                                                                when x"D" =>    --------------------------------------------------------------------------- LD r2,r1,X instruction
1321
                                                                                        FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
1322
                                                                                        DEST_ADDR := RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
1323
                                                                                        RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1324
                                                                                        NUM_BYTES := 3;
1325
                                                                                        CPU_STATE := CPU_MTOXAD;
1326
                                                                                when x"F" =>    ------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
1327
                                                                                when others =>  ----------------------------------------------------------------------------- IR1,imm instructions
1328
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1329
                                                                                        TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1330
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1331
                                                                                        NUM_BYTES := 3;
1332
                                                                                        CPU_STATE := CPU_IND1;
1333
                                                                        end case;
1334
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"6") then -------------------------------------------- column 6 instructions
1335
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1336
                                                                                when x"8" =>    -------------------------------------------------------------------------- LDX IRR2,R1 instruction
1337
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1338
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1339
                                                                                        NUM_BYTES := 3;
1340
                                                                                        LU_INSTRUCTION := '1';  -- in this mode this flag is used to signal the direct register addressing mode
1341
                                                                                        CPU_STATE := CPU_IRRS;
1342
                                                                                when x"9" =>    -------------------------------------------------------------------------- LDX R2,IRR1 instruction
1343
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1344
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1345
                                                                                        NUM_BYTES := 3;
1346
                                                                                        CPU_STATE := CPU_MTOIRR;
1347
                                                                                when x"C" =>    -- illegal, decoded at 1-byte decoder
1348
                                                                                        --CPU_STATE := CPU_ILLEGAL;     -- uncommenting this adds +400 LEs to the design!!!
1349
                                                                                when x"D" =>    ------------------------------------------------------------------------------ CALL DA instruction
1350
                                                                                when x"F" =>    ------------------------------------------------------------------------- BTJ p,b,r1,X instruction
1351
                                                                                when others =>  ------------------------------------------------------------------------------ R1,imm instructions
1352
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1353
                                                                                        TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1354
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1355
                                                                                        NUM_BYTES := 3;
1356
                                                                                        CPU_STATE := CPU_OMA;
1357
                                                                        end case;
1358
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"5") then -------------------------------------------- column 5 instructions
1359
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1360
                                                                                when x"8" =>    -------------------------------------------------------------------------- LDX Ir1,ER2 instruction
1361
                                                                                        FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1362
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                      -- dest address
1363
                                                                                        NUM_BYTES := 3;
1364
                                                                                        CPU_STATE := CPU_IND2;
1365
                                                                                when x"9" =>    -------------------------------------------------------------------------- LDX Ir2,ER1 instruction
1366
                                                                                        FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
1367
                                                                                        DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1368
                                                                                        NUM_BYTES := 3;
1369
                                                                                        CPU_STATE := CPU_ISMD1;
1370
                                                                                when x"C" =>    ------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
1371
                                                                                when x"D" =>    ----------------------------------------------------------------------------- BSWAP R1 instruction
1372
                                                                                when x"F" =>    ---------------------------------------------------------------------------- LD R2,IR1 instruction
1373
                                                                                when others =>  ------------------------------------------------------------------------------ IR2,R1 instructions
1374
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1375
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1376
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1377
                                                                                        NUM_BYTES := 3;
1378
                                                                                        CPU_STATE := CPU_ISMD1;
1379
                                                                        end case;
1380
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"4") then -------------------------------------------- column 4 instructions
1381
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1382
                                                                                when x"8" =>    --------------------------------------------------------------------------- LDX r1,ER2 instruction
1383
                                                                                        FRAB <= IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1384
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                      -- dest address
1385
                                                                                        NUM_BYTES := 3;
1386
                                                                                        CPU_STATE := CPU_TMA;
1387
                                                                                when x"9" =>    --------------------------------------------------------------------------- LDX r2,ER1 instruction
1388
                                                                                        FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);
1389
                                                                                        DEST_ADDR := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1390
                                                                                        NUM_BYTES := 3;
1391
                                                                                        CPU_STATE := CPU_TMA;
1392
                                                                                when x"C" =>    ------------------------------------------------------------------------------ JP Irr1 instruction
1393
                                                                                when x"D" =>    ---------------------------------------------------------------------------- CALL Irr1 instruction
1394
                                                                                when x"F" =>    ----------------------------------------------------------------------------- MULT RR1 instruction
1395
                                                                                when others =>  ------------------------------------------------------------------------------- R2,R1 instructions
1396
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1397
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1398
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1399
                                                                                        NUM_BYTES := 3;
1400
                                                                                        CPU_STATE := CPU_TMA;
1401
                                                                        end case;
1402
                                                                end if;
1403
                                                                ------------------------------------------------------------------------------------------------- BTJ p,b,r1,X instruction
1404
                                                                ------------------------------------------------------------------------------------------------ BTJ p,b,Ir1,X instruction
1405
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F6" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F7") then
1406
                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1407
                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);    -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
1408
                                                                        RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);                                 -- RESULT has the offset X
1409
                                                                        NUM_BYTES := 3;
1410
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS)(0)='0') then CPU_STATE := CPU_BTJ; else CPU_STATE := CPU_IBTJ;
1411
                                                                        end if;
1412
                                                                ---------------------------------------------------------------------------------------------------- LD R2,IR1 instruction
1413
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F5") then
1414
                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1415
                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1416
                                                                        NUM_BYTES := 3;
1417
                                                                        CPU_STATE := CPU_IND2;
1418
                                                                ------------------------------------------------------------------------------------------------------ CALL DA instruction
1419
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D6") then
1420
                                                                        DEST_ADDR16 := PC + 3;
1421
                                                                        PC := IQUEUE.QUEUE(IQUEUE.RDPOS+1) & IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1422
                                                                        SP := SP - 1;
1423
                                                                        FRAB <= SP;
1424
                                                                        LU_INSTRUCTION := '0';   -- this is used to indicate wether the stacking is due to a CALL or INT, 0 for a CALL
1425
                                                                        IQUEUE.FETCH_STATE := F_ADDR;
1426
                                                                        CPU_STATE := CPU_STACK;
1427
                                                                ---------------------------------------------------------------------------------------------------- 2nd page instructions
1428
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"1F") then
1429
                                                                        -------------------------------------------------------------------------------------------------- PUSH IM instruction
1430
                                                                        if (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"70") then
1431
                                                                                SP := SP - 1;
1432
                                                                                FRAB <= SP;
1433 2 fabiop
                                                                                TEMP_DATA := IQUEUE.QUEUE(IQUEUE.RDPOS+2);
1434
                                                                                NUM_BYTES := 3;
1435 3 fabiop
                                                                                CPU_STATE := CPU_OMA;
1436
                                                                        ------------------------------------------------------------------------------------------------ CPC r1,r2 instruction
1437
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A2") then
1438
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0));                                                    -- source address                               
1439
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));                                              -- dest address
1440
                                                                                TEMP_OP := ALU_CPC;
1441 2 fabiop
                                                                                NUM_BYTES := 3;
1442 3 fabiop
                                                                                CPU_STATE := CPU_TMA;
1443
                                                                        ----------------------------------------------------------------------------------------------- CPC r1,Ir2 instruction
1444
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"A3") then
1445
                                                                                FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(3 downto 0));                                                    -- source address                               
1446
                                                                                DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+2)(7 downto 4));                                              -- dest address
1447
                                                                                TEMP_OP := ALU_CPC;
1448 2 fabiop
                                                                                NUM_BYTES := 3;
1449 3 fabiop
                                                                                CPU_STATE := CPU_ISMD1;
1450
                                                                        --------------------------------------------------------------------------------------------------- SRL R1 instruction
1451
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C0") then
1452
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1453
                                                                                TEMP_OP := LU2_SRL;
1454 2 fabiop
                                                                                NUM_BYTES := 3;
1455 3 fabiop
                                                                                CPU_STATE := CPU_OMA2;
1456
                                                                        -------------------------------------------------------------------------------------------------- SRL IR1 instruction
1457
                                                                        elsif (IQUEUE.QUEUE(IQUEUE.RDPOS+1)=x"C1") then
1458
                                                                                FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+2));
1459
                                                                                TEMP_OP := LU2_SRL;
1460 2 fabiop
                                                                                NUM_BYTES := 3;
1461 3 fabiop
                                                                                CPU_STATE := CPU_IND1;
1462
                                                                                LU_INSTRUCTION := '1';
1463
                                                                        end if;
1464 2 fabiop
                                                                end if;
1465
                                                        end if;
1466 3 fabiop
 
1467
                                                        ------------------------------------------------------------------------------------------------------------------------------
1468
                                                        --**************************************************************************************************************************--
1469
                                                        --                                                     2-byte instructions                                                  --
1470
                                                        --**************************************************************************************************************************--
1471
                                                        ------------------------------------------------------------------------------------------------------------------------------
1472
                                                        if (IQUEUE.CNT>=2) then -- 2-byte instructions
1473
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"C") then    ------------------------------------------------- LD r,IMM instruction
1474
                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
1475
                                                                        DATAWRITE(ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4)),IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1476
                                                                        NUM_BYTES := 2;
1477
                                                                        CPU_STATE := CPU_STORE;
1478
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"B") then -------------------------------------------- JR cc,RelativeAddress
1479
                                                                        PC := PC + 2;
1480
                                                                        if (CONDITIONCODE(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4))='1') then
1481
                                                                                PC := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1482
                                                                                IQUEUE.FETCH_STATE := F_ADDR;
1483
                                                                        else
1484
                                                                                IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
1485
                                                                                IQUEUE.CNT := IQUEUE.CNT - 2;
1486
                                                                        end if;
1487
                                                                        CPU_STATE := CPU_DECOD;
1488
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"A") then ------------------------------------------- DJNZ r,RelativeAddress
1489
                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4));
1490
                                                                        PC := PC + 2;
1491
                                                                        DEST_ADDR16 := ADDER16(PC,IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1492
                                                                        IQUEUE.RDPOS := IQUEUE.RDPOS + 2;
1493
                                                                        IQUEUE.CNT := IQUEUE.CNT - 2;
1494 2 fabiop
                                                                        IQUEUE.FETCH_STATE := F_ADDR;
1495 3 fabiop
                                                                        CPU_STATE := CPU_DJNZ;
1496
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"3") then -------------------------------------------- column 3 instructions
1497
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1498
                                                                                when x"8" =>    ------------------------------------------------------------------------ LDEI Ir1,Irr2 instruction
1499
                                                                                when x"9" =>    ------------------------------------------------------------------------ LDEI Ir2,Irr1 instruction
1500
                                                                                when x"C" =>    ------------------------------------------------------------------------ LDCI Ir1,Irr2 instruction
1501
                                                                                        RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
1502
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1503
                                                                                        NUM_BYTES := 2;
1504
                                                                                        CAN_FETCH := '0';
1505
                                                                                        LU_INSTRUCTION := '0';   -- indicates it is a read from program memory
1506
                                                                                        WORD_DATA := '1';               -- indicates it is a LDCI instruction
1507
                                                                                        CPU_STATE := CPU_LDPTOIM;
1508
                                                                                when x"D" =>    ------------------------------------------------------------------------ LDCI Ir2,Irr1 instruction
1509
                                                                                        RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
1510
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1511
                                                                                        NUM_BYTES := 2;
1512
                                                                                        CAN_FETCH := '0';
1513
                                                                                        LU_INSTRUCTION := '1';  -- indicates it is a write onto program memory
1514
                                                                                        WORD_DATA := '1';               -- indicates it is a LDCI instruction
1515
                                                                                        CPU_STATE := CPU_LDPTOIM;
1516
                                                                                when x"F" =>    ---------------------------------------------------------------------------- LD Ir1,r2 instruction
1517
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
1518
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1519
                                                                                        NUM_BYTES := 2;
1520
                                                                                        CPU_STATE := CPU_IND2;
1521
                                                                                when others =>  --------------------------------------------------------------------------- Ir2 to r1 instructions
1522
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1523
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1524
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1525
                                                                                        NUM_BYTES := 2;
1526
                                                                                        CPU_STATE := CPU_ISMD1;
1527
                                                                        end case;
1528
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"2") then -------------------------------------------- column 2 instructions
1529
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1530
                                                                                when x"8" =>    -------------------------------------------------------------------------- LDE r1,Irr2 instruction
1531
                                                                                when x"9" =>    -------------------------------------------------------------------------- LDE r2,Irr1 instruction
1532
                                                                                when x"C" =>    -------------------------------------------------------------------------- LDC r1,Irr2 instruction
1533
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
1534
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1535
                                                                                        NUM_BYTES := 2;
1536
                                                                                        CAN_FETCH := '0';
1537
                                                                                        LU_INSTRUCTION := '0';
1538
                                                                                        CPU_STATE := CPU_LDPTOM;
1539
                                                                                when x"D" =>    -------------------------------------------------------------------------- LDC r2,Irr1 instruction
1540
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
1541
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1542
                                                                                        NUM_BYTES := 2;
1543
                                                                                        CAN_FETCH := '0';
1544
                                                                                        LU_INSTRUCTION := '1';
1545
                                                                                        CPU_STATE := CPU_LDPTOM;
1546
                                                                                when x"E" =>    --------------------------------------------------------------------------- BIT p,b,r1 instruction
1547
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));
1548
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4);    -- TEMP_OP has the polarity (bit 3) and bit number (bits 2:0)
1549
                                                                                        RESULT := IQUEUE.QUEUE(IQUEUE.RDPOS+2);                                 -- RESULT has the offset X
1550
                                                                                        NUM_BYTES := 2;
1551
                                                                                        CPU_STATE := CPU_BIT;
1552
                                                                                when x"F" =>    ----------------------------------------------------------------------------- TRAP imm instruction
1553
                                                                                        FRAB <= "000" & IQUEUE.QUEUE(IQUEUE.RDPOS+1) & '0';
1554
                                                                                        DEST_ADDR16 := PC + 2;
1555
                                                                                        NUM_BYTES := 2;
1556
                                                                                        CPU_STATE := CPU_TRAP;
1557
                                                                                when others =>  ---------------------------------------------------------------------------- r2 to r1 instructions
1558
                                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0));                                                    -- source address                               
1559
                                                                                        DEST_ADDR := ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));                                              -- dest address
1560
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1561
                                                                                        NUM_BYTES := 2;
1562
                                                                                        CPU_STATE := CPU_TMA;
1563
                                                                        end case;
1564
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"1") then -------------------------------------------- column 1 instructions
1565
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1566
                                                                                when x"0" =>     ------------------------------------------------------------------------------ SRP IMM instruction      
1567
                                                                                        RP := IQUEUE.QUEUE(IQUEUE.RDPOS+1);
1568
                                                                                        NUM_BYTES := 2;
1569
                                                                                        CPU_STATE := CPU_DECOD;
1570
                                                                                when x"5" =>    ------------------------------------------------------------------------------ POP IR1 instruction
1571
                                                                                        FRAB <= SP;
1572
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1573
                                                                                        SP := SP + 1;
1574
                                                                                        NUM_BYTES := 2;
1575
                                                                                        CPU_STATE := CPU_IND2;
1576
                                                                                when x"7" =>    ----------------------------------------------------------------------------- PUSH IR1 instruction
1577
                                                                                        SP := SP - 1;
1578
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1579
                                                                                        DEST_ADDR := SP;
1580
                                                                                        NUM_BYTES := 2;
1581
                                                                                        CPU_STATE := CPU_ISMD1;
1582
                                                                                when x"8" =>    --------------------------------------------------------------------------------- DECW instruction
1583
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1584
                                                                                        TEMP_OP := LU2_DEC;
1585
                                                                                        WORD_DATA := '1';
1586
                                                                                        NUM_BYTES := 2;
1587
                                                                                        CPU_STATE := CPU_INDRR;
1588
                                                                                when x"A" =>    --------------------------------------------------------------------------------- INCW instruction
1589
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1590
                                                                                        TEMP_OP := LU2_INC;
1591
                                                                                        WORD_DATA := '1';
1592
                                                                                        NUM_BYTES := 2;
1593
                                                                                        CPU_STATE := CPU_INDRR;
1594
                                                                                when others =>  --------------------------------------------------------------------------------- IR1 instructions
1595
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1596
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1597
                                                                                        NUM_BYTES := 2;
1598
                                                                                        CPU_STATE := CPU_IND1;
1599
                                                                                        LU_INSTRUCTION := '1';
1600
                                                                        end case;
1601
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"0") then  -------------------------------------------- column 0 instructions
1602
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1603
                                                                                when x"0" =>     ---------------------------------------------------------------------------------- BRK instruction      
1604
                                                                                        -- do nothing, BRK decoding is done in 1-byte instruction section
1605
                                                                                when x"5" =>    ---------------------------------------------------------------------------------- POP instruction
1606
                                                                                        FRAB <= SP;
1607
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1608
                                                                                        SP := SP + 1;
1609
                                                                                        NUM_BYTES := 2;
1610
                                                                                        CPU_STATE := CPU_TMA;
1611
                                                                                when x"7" =>    --------------------------------------------------------------------------------- PUSH instruction
1612
                                                                                        SP := SP - 1;
1613
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1614
                                                                                        DEST_ADDR := SP;
1615
                                                                                        NUM_BYTES := 2;
1616
                                                                                        CPU_STATE := CPU_TMA;
1617
                                                                                when x"8" =>    --------------------------------------------------------------------------------- DECW instruction
1618
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1619
                                                                                        FRAB <= DEST_ADDR+1;
1620
                                                                                        TEMP_OP := LU2_DEC;
1621
                                                                                        WORD_DATA := '1';
1622
                                                                                        NUM_BYTES := 2;
1623
                                                                                        CPU_STATE := CPU_OMA2;
1624
                                                                                when x"A" =>    --------------------------------------------------------------------------------- INCW instruction
1625
                                                                                        DEST_ADDR := ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1626
                                                                                        FRAB <= DEST_ADDR+1;
1627
                                                                                        TEMP_OP := LU2_INC;
1628
                                                                                        WORD_DATA := '1';
1629
                                                                                        NUM_BYTES := 2;
1630
                                                                                        CPU_STATE := CPU_OMA2;
1631
                                                                                when others =>  ---------------------------------------------------------------------------------- R1 instructions
1632
                                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1633
                                                                                        TEMP_OP := IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1634
                                                                                        NUM_BYTES := 2;
1635
                                                                                        CPU_STATE := CPU_OMA2;
1636
                                                                        end case;
1637
                                                                end if;
1638
                                                                ---------------------------------------------------------------------------------------------------------- MUL instruction 
1639
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F4") then
1640
                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1641
                                                                        NUM_BYTES := 2;
1642
                                                                        CPU_STATE := CPU_MUL;
1643
                                                                ---------------------------------------------------------------------------------------------------- CALL IRR1 instruction
1644
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D4") then
1645
                                                                        DEST_ADDR16 := PC + 2;
1646
                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1647
                                                                        IQUEUE.FETCH_STATE := F_ADDR;
1648
                                                                        CPU_STATE := CPU_INDSTACK;
1649
                                                                ------------------------------------------------------------------------------------------------------ JP IRR1 instruction
1650
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C4") then
1651
                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1652
                                                                        IQUEUE.FETCH_STATE := F_ADDR;
1653
                                                                        CPU_STATE := CPU_INDJUMP;
1654
                                                                ----------------------------------------------------------------------------------------------------- BSWAP R1 instruction
1655
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D5") then
1656
                                                                        FRAB <= ADDRESSER8(IQUEUE.QUEUE(IQUEUE.RDPOS+1));
1657
                                                                        TEMP_OP := ALU_BSWAP;
1658
                                                                        NUM_BYTES := 2;
1659
                                                                        CPU_STATE := CPU_OMA;
1660
                                                                ------------------------------------------------------------------------------------------------- LDC Ir1,Irr2 instruction
1661
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C5") then
1662
                                                                        RESULT(3 downto 0) := IQUEUE.QUEUE(IQUEUE.RDPOS+1)(3 downto 0);
1663
                                                                        FRAB <= ADDRESSER4(IQUEUE.QUEUE(IQUEUE.RDPOS+1)(7 downto 4));
1664
                                                                        NUM_BYTES := 2;
1665
                                                                        CAN_FETCH := '0';
1666
                                                                        LU_INSTRUCTION := '0';
1667
                                                                        CPU_STATE := CPU_LDPTOIM;
1668 2 fabiop
                                                                end if;
1669
                                                        end if;
1670 3 fabiop
 
1671
                                                        ------------------------------------------------------------------------------------------------------------------------------
1672
                                                        --**************************************************************************************************************************--
1673
                                                        --                                                     1-byte instructions                                                  --
1674
                                                        --**************************************************************************************************************************--
1675
                                                        ------------------------------------------------------------------------------------------------------------------------------
1676
                                                        if (IQUEUE.CNT>=1) then -- 1-byte instructions
1677
                                                                if (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"F") then    ------------------------------------------------ column F instructions
1678
                                                                        case IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4) is
1679
                                                                                when x"0" =>     ---------------------------------------------------------------------------------- NOP instruction      
1680
                                                                                        NUM_BYTES := 1;
1681
                                                                                when x"1" =>    ------------------------------------------------------------------------------ page 2 instructions
1682
                                                                                when x"2" =>
1683
                                                                                        ATM_COUNTER := 0;
1684
                                                                                        NUM_BYTES := 1;
1685
                                                                                when x"3" =>
1686
                                                                                        CPU_STATE := CPU_ILLEGAL;
1687
                                                                                when x"4" =>
1688
                                                                                        CPU_STATE := CPU_ILLEGAL;
1689
                                                                                when x"5" =>    ---------------------------------------------------------------------------------- WDT instruction
1690
                                                                                        NUM_BYTES := 1;
1691
                                                                                when x"6" =>    --------------------------------------------------------------------------------- STOP instruction
1692
                                                                                        NUM_BYTES := 1;
1693
                                                                                        STOP <= '1';
1694
                                                                                when x"7" =>    --------------------------------------------------------------------------------- HALT instruction
1695
                                                                                        NUM_BYTES := 1;
1696
                                                                                        HALT := '1';
1697
                                                                                when x"8" =>    ----------------------------------------------------------------------------------- DI instruction
1698
                                                                                        IRQE := '0';
1699
                                                                                        NUM_BYTES := 1;
1700
                                                                                when x"9" =>    ----------------------------------------------------------------------------------- EI instruction
1701
                                                                                        IRQE := '1';
1702
                                                                                        NUM_BYTES := 1;
1703
                                                                                when x"A" =>    ---------------------------------------------------------------------------------- RET instruction
1704
                                                                                        NUM_BYTES := 1;
1705
                                                                                        FRAB <= SP;
1706
                                                                                        CPU_STATE := CPU_UNSTACK2;
1707
                                                                                when x"B" =>    --------------------------------------------------------------------------------- IRET instruction
1708
                                                                                        NUM_BYTES := 1;
1709
                                                                                        IRQE := '1';
1710
                                                                                        FRAB <= SP;
1711
                                                                                        CPU_STATE := CPU_UNSTACK3;
1712
                                                                                when x"C" =>    ---------------------------------------------------------------------------------- RCF instruction
1713
                                                                                        CPU_FLAGS.C := '0';
1714
                                                                                        NUM_BYTES := 1;
1715
                                                                                when x"D" =>    ---------------------------------------------------------------------------------- SCF instruction
1716
                                                                                        CPU_FLAGS.C := '1';
1717
                                                                                        NUM_BYTES := 1;
1718
                                                                                when x"E" =>    ---------------------------------------------------------------------------------- CCF instruction
1719
                                                                                        CPU_FLAGS.C := not CPU_FLAGS.C;
1720
                                                                                        NUM_BYTES := 1;
1721
                                                                                when others =>  ---------------------------------------------------------------------------------- R1 instructions
1722
                                                                                        CPU_STATE := CPU_ILLEGAL;
1723
                                                                        end case;
1724
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)(3 downto 0)=x"E") then ------------------------------------------------ INC r instruction
1725
                                                                        FRAB <= RP(3 downto 0) & RP(7 downto 4) & IQUEUE.QUEUE(IQUEUE.RDPOS)(7 downto 4);
1726
                                                                        TEMP_OP := LU2_INC;
1727
                                                                        NUM_BYTES := 1;
1728
                                                                        CPU_STATE := CPU_OMA2;
1729
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"00") then   -------------------------------------------------------------- BRK instruction
1730
                                                                        if (OCDCR.BRKEN='1') then               -- the BRK instruction is enabled
1731
                                                                                if (OCDCR.DBGACK='1') then
1732
                                                                                        if (DBG_UART.TX_EMPTY='1') then
1733
                                                                                                DBG_UART.TX_DATA:=x"FF";
1734
                                                                                                DBG_UART.TX_EMPTY:='0';
1735
                                                                                        end if;
1736 2 fabiop
                                                                                end if;
1737 3 fabiop
                                                                                if (OCDCR.BRKLOOP='0') then      -- if loop on BRK is disabled
1738
                                                                                        OCDCR.DBGMODE := '1';   -- set DBGMODE halting CPU
1739
                                                                                end if;
1740
                                                                        else
1741
                                                                                NUM_BYTES := 1;                 -- remove the instruction from queue (execute as a NOP)
1742 2 fabiop
                                                                        end if;
1743 3 fabiop
                                                                elsif (IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"D9" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F9" or
1744
                                                                                IQUEUE.QUEUE(IQUEUE.RDPOS)=x"F8" or IQUEUE.QUEUE(IQUEUE.RDPOS)=x"C6") then      --------------------------- illegal opcode
1745
                                                                        CPU_STATE:= CPU_ILLEGAL;
1746
                                                                        NUM_BYTES := 1;
1747 2 fabiop
                                                                end if;
1748
                                                        end if;
1749 3 fabiop
                                                end if; -- if DBGMODE=0...
1750
                                        end if; -- if not stopped or halted
1751
                                        PC := PC + NUM_BYTES;                                           -- update PC after instruction
1752
                                        IQUEUE.RDPOS := IQUEUE.RDPOS + NUM_BYTES;       -- update QUEUE read pointer
1753
                                        IQUEUE.CNT := IQUEUE.CNT - NUM_BYTES;           -- update QUEUE available bytes
1754
                                        if (OCD.SINGLESTEP='1') then                                                                                                    -- if we are stepping instructions
1755
                                                if (NUM_BYTES/=0 or IQUEUE.FETCH_STATE=F_ADDR) then OCD.SINGLESTEP:='0';  -- if a instruction was decoded, reset step flag
1756 2 fabiop
                                                end if;
1757
                                        end if;
1758
                                when CPU_MUL => -- MUL ***********************************************************************************************************
1759 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);            -- read first operand
1760
                                        FRAB <= FRAB + 1;                                       -- go to the next operand 
1761 2 fabiop
                                        CPU_STATE := CPU_MUL1;
1762
                                when CPU_MUL1 =>
1763 3 fabiop
                                        DEST_ADDR16 := TEMP_DATA * DATAREAD(FRAB);      -- multiply previous operand by the second operand and store temporarily
1764
                                        DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- prepare to write the lower byte in current memory address 
1765 2 fabiop
                                        WR <= '1';
1766
                                        CPU_STATE := CPU_MUL2;
1767
                                when CPU_MUL2 =>
1768 3 fabiop
                                        FRAB <= FRAB - 1;                                                       -- decrement memory address (point to the first operand)
1769
                                        DATAWRITE(FRAB,DEST_ADDR16(15 downto 8));       -- write the higher byte
1770 2 fabiop
                                        CPU_STATE := CPU_STORE;                                         -- complete store operation
1771
                                when CPU_XRRTORR =>     -- LEA *******************************************************************************************************
1772 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);                            -- read the operand and store it
1773
                                        FRAB <= FRAB + 1;                                                       -- go to the next memory address
1774 2 fabiop
                                        CPU_STATE := CPU_XRRTORR2;
1775
                                when CPU_XRRTORR2 =>
1776 3 fabiop
                                        -- read next operand and perform a 16 bit add with the offset previously in result
1777
                                        DEST_ADDR16 := ADDER16(TEMP_DATA & DATAREAD(FRAB),RESULT);
1778
                                        FRAB <= DEST_ADDR;                                                      -- point to the destination address
1779
                                        DATAWRITE(FRAB,DEST_ADDR16(15 downto 8));       -- store the higher byte of the 16-bit result
1780 2 fabiop
                                        CPU_STATE := CPU_XRRTORR3;
1781
                                when CPU_XRRTORR3 =>
1782
                                        WR <= '1';
1783
                                        CPU_STATE := CPU_XRRTORR4;
1784
                                when CPU_XRRTORR4 =>
1785 3 fabiop
                                        FRAB <= FRAB + 1;                                                       -- go to the next memory address
1786
                                        DATAWRITE(FRAB,DEST_ADDR16(7 downto 0)); -- store the lower byte of the 16-bit result
1787 2 fabiop
                                        CPU_STATE := CPU_STORE;                                         -- complete store operation
1788
                                when CPU_MTOXAD =>      -- MEMORY TO INDEXED 8-BIT ADDRESS ***************************************************************************
1789 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);                            -- read operand from memory
1790
                                        FRAB <= DEST_ADDR;                                                      -- update address bus with destination address
1791 2 fabiop
                                        CPU_STATE := CPU_MTOXAD2;
1792
                                when CPU_MTOXAD2 =>
1793 3 fabiop
                                        FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT);        -- update address bus indexed result
1794
                                        DATAWRITE(FRAB,TEMP_DATA);                                      -- prepare to write data on destination (indexed) address
1795
                                        CPU_STATE := CPU_STORE;                                         -- perform store (WR=1)
1796 2 fabiop
                                when CPU_XADTOM =>      -- INDEXED 8-BIT ADDRESS TO MEMORY ***************************************************************************
1797 3 fabiop
                                        FRAB <= RP(3 downto 0)&(DATAREAD(FRAB) + RESULT);
1798 2 fabiop
                                        CPU_STATE := CPU_TMA;
1799
                                when CPU_XRTOM =>       -- LEA *******************************************************************************************************
1800 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB)+RESULT;
1801
                                        FRAB <= DEST_ADDR;
1802
                                        DATAWRITE(FRAB,TEMP_DATA);
1803 2 fabiop
                                        CPU_STATE := CPU_STORE;
1804
                                when CPU_IMTOIRR =>     -- INDIRECT MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ***********************************************
1805 3 fabiop
                                        FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
1806 2 fabiop
                                        CPU_STATE := CPU_MTOIRR;
1807
                                when CPU_MTOIRR =>      -- MEMORY TO INDIRECT ADDRESS READ FROM REGISTER PAIR ********************************************************
1808 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);                            -- reads data from the source (FRAB) address and store it into TEMP_DATA
1809
                                        FRAB <= DEST_ADDR;                                                      -- FRAB points to the indirect destination register pair
1810 2 fabiop
                                        RESULT := x"00";
1811 3 fabiop
                                        CPU_STATE := CPU_XRRD2;                                         -- proceed as X indexed register pair destination
1812 2 fabiop
                                when CPU_IRRS =>        -- RR PAIR AS INDIRECT SOURCE ADDRESS ************************************************************************
1813 3 fabiop
                                        DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
1814
                                        FRAB <= FRAB + 1;
1815 2 fabiop
                                        CPU_STATE := CPU_IRRS2;
1816
                                when CPU_IRRS2 =>
1817 3 fabiop
                                        DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
1818
                                        FRAB <= DEST_ADDR16(11 downto 0);
1819 2 fabiop
                                        if (LU_INSTRUCTION='1') then
1820
                                                CPU_STATE:= CPU_TMA;                            -- if it is direct addressing mode, go to TMA
1821
                                        else
1822
                                                CPU_STATE := CPU_IND2;                          -- if it is indirect addressing mode, go to IND2
1823
                                        end if;
1824 3 fabiop
                                when CPU_XRRD =>        -- RR PAIR PLUS OFFSET AS DESTINATION ADDRESS ****************************************************************
1825
                                        TEMP_DATA := DATAREAD(FRAB);                            -- reads data from the source (FRAB) address and store it into TEMP_DATA
1826
                                        FRAB <= DEST_ADDR;
1827 2 fabiop
                                        CPU_STATE := CPU_XRRD2;
1828
                                when CPU_XRRD2 =>
1829 3 fabiop
                                        DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
1830
                                        FRAB <= FRAB + 1;
1831 2 fabiop
                                        CPU_STATE := CPU_XRRD3;
1832
                                when CPU_XRRD3 =>
1833 3 fabiop
                                        DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
1834
                                        FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
1835
                                        DATAWRITE(FRAB,TEMP_DATA);
1836 2 fabiop
                                        CPU_STATE := CPU_STORE;
1837 3 fabiop
                                when CPU_XRRS =>        -- RR PAIR PLUS OFFSET AS SOURCE ADDRESS *********************************************************************
1838
                                        DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
1839
                                        FRAB <= FRAB + 1;
1840 2 fabiop
                                        CPU_STATE := CPU_XRRS2;
1841
                                when CPU_XRRS2 =>
1842 3 fabiop
                                        DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
1843
                                        FRAB <= ADDER16(DEST_ADDR16,RESULT)(11 downto 0);
1844 2 fabiop
                                        CPU_STATE := CPU_XRRS3;
1845
                                when CPU_XRRS3 =>
1846 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);
1847
                                        FRAB <= DEST_ADDR;
1848
                                        DATAWRITE(FRAB,TEMP_DATA);
1849 2 fabiop
                                        CPU_STATE := CPU_STORE;
1850
                                when CPU_INDRR =>       -- INDIRECT DESTINATION ADDRESS FOR WORD INSTRUCTIONS (DECW AND INCW) ****************************************
1851 3 fabiop
                                        FRAB <= (RP(3 downto 0) & DATAREAD(FRAB))+1;     -- the destination address is given by indirect address
1852 2 fabiop
                                        CPU_STATE := CPU_OMA2;
1853
                                when CPU_ISMD1 =>       -- INDIRECT SOURCE ADDRESS ***********************************************************************************
1854 3 fabiop
                                        FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- source address is read from indirect register
1855 2 fabiop
                                        CPU_STATE := CPU_TMA;
1856
                                when CPU_IND2 =>        -- READS REGISTER AND PERFORM OPERATION ON AN INDIRECT DESTINATION *******************************************
1857 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);                            -- reads data from the source (FRAB) address and store it into TEMP_DATA
1858
                                        FRAB <= DEST_ADDR;                                              -- place the address of the indirect register on FRAB
1859 2 fabiop
                                        CPU_STATE := CPU_IND1;                                  -- proceed to the indirect
1860
                                when CPU_IND1 =>        -- INDIRECT DESTINATION ADDRESS ******************************************************************************
1861 3 fabiop
                                        FRAB <= RP(3 downto 0) & DATAREAD(FRAB); -- the destination address is given by indirect address
1862 2 fabiop
                                        if (LU_INSTRUCTION='0') then CPU_STATE := CPU_OMA;                                       -- proceed with one memory access
1863
                                        else CPU_STATE := CPU_OMA2;                                                                                     -- proceed with one memory access (logic unit related)
1864
                                        end if;
1865
                                when CPU_TMA =>         -- TWO MEMORY ACCESS, READS SOURCE OPERAND FROM MEMORY *******************************************************
1866 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);                    -- reads data from the source (FRAB) address and store it into TEMP_DATA
1867
                                        FRAB <= DEST_ADDR;                                              -- place destination address (DEST_ADDR) on memory address bus (FRAB)
1868 2 fabiop
                                        CPU_STATE := CPU_OMA;                                   -- proceed to the last stage
1869
                                when CPU_OMA =>         -- ONE MEMORY ACCESS stage ***********************************************************************************
1870 3 fabiop
                                        -- this stage performs TEMP_OP operation between TEMP_DATA and data read from current (FRAB) address (destination)
1871
                                        RESULT := ALU(TEMP_OP,DATAREAD(FRAB),TEMP_DATA,CPU_FLAGS.C);
1872 2 fabiop
                                        if (TEMP_OP<ALU_OR) then
1873
                                                CPU_FLAGS.C := ALU_FLAGS.C;
1874
                                                CPU_FLAGS.V := ALU_FLAGS.V;
1875
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1876
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1877
                                                CPU_FLAGS.H := ALU_FLAGS.H;
1878
                                                CPU_FLAGS.D := TEMP_OP(1);
1879
                                        elsif (TEMP_OP=ALU_CP or TEMP_OP=ALU_CPC) then
1880
                                                CPU_FLAGS.C := ALU_FLAGS.C;
1881
                                                CPU_FLAGS.V := ALU_FLAGS.V;
1882
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1883
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1884
                                        elsif (TEMP_OP/=ALU_LD) then
1885
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1886
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1887
                                                CPU_FLAGS.V := '0';
1888
                                        end if;
1889
                                        if (ALU_NOUPDATE='0') then
1890 3 fabiop
                                                DATAWRITE(FRAB,RESULT);
1891 2 fabiop
                                                WR <= '1';
1892
                                        end if;
1893
                                        CPU_STATE := CPU_DECOD;
1894
                                        if (WORD_DATA='1') then
1895
                                                CPU_STATE := CPU_LDW;
1896
                                        end if;
1897
                                when CPU_OMA2 =>        -- ONE MEMORY ACCESS stage logic unit related ****************************************************************
1898 3 fabiop
                                        -- this stage performs TEMP_OP LU2 operation on data read from current (FRAB) address
1899
                                        RESULT := LU2(TEMP_OP,DATAREAD(FRAB),CPU_FLAGS.D,CPU_FLAGS.H,CPU_FLAGS.C);
1900 2 fabiop
                                        if (TEMP_OP=LU2_DEC or TEMP_OP=LU2_INC) then
1901
                                                CPU_FLAGS.V := ALU_FLAGS.V;
1902
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1903
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1904
                                        elsif (TEMP_OP=LU2_COM) then
1905
                                                CPU_FLAGS.V := '0';
1906
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1907
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1908
                                        elsif (TEMP_OP=LU2_SWAP) then
1909
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1910
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1911
                                        elsif (TEMP_OP=LU2_DA) then
1912
                                                CPU_FLAGS.C := ALU_FLAGS.C;
1913
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1914
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1915
                                        elsif (TEMP_OP=LU2_LD) then
1916
                                                CPU_FLAGS.V := ALU_FLAGS.V;
1917
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1918
                                                CPU_FLAGS.Z := CPU_FLAGS.Z and ALU_FLAGS.Z;
1919
                                        elsif (TEMP_OP/=LU2_CLR) then
1920
                                                CPU_FLAGS.C := ALU_FLAGS.C;
1921
                                                CPU_FLAGS.V := ALU_FLAGS.V;
1922
                                                CPU_FLAGS.Z := ALU_FLAGS.Z;
1923
                                                CPU_FLAGS.S := ALU_FLAGS.S;
1924
                                        end if;
1925 3 fabiop
                                        DATAWRITE(FRAB,RESULT);
1926 2 fabiop
                                        WR <= '1';
1927
                                        if (WORD_DATA='1') then
1928
                                                WORD_DATA := '0';
1929
                                                if (ALU_FLAGS.C='0') then TEMP_OP := LU2_LD;
1930
                                                end if;
1931
                                                CPU_STATE := CPU_DMAB;
1932
                                        else CPU_STATE := CPU_DECOD;
1933
                                        end if;
1934 3 fabiop
                                when CPU_DMAB =>        -- DECREMENT MEMORY ADDRESS BUS ******************************************************************************
1935
                                        FRAB <= FRAB - 1;
1936 2 fabiop
                                        CPU_STATE := CPU_OMA2;
1937 3 fabiop
                                when CPU_LDW =>         -- LOAD WORD INSTRUCTION *************************************************************************************
1938
                                        -- read higher byte from source operand
1939
                                        TEMP_DATA := DATAREAD(FRAB);
1940
                                        FRAB <= FRAB + 1;
1941 2 fabiop
                                        CPU_STATE := CPU_LDW2;
1942
                                when CPU_LDW2 =>
1943 3 fabiop
                                        -- read lower byte from source operand
1944
                                        RESULT := DATAREAD(FRAB);
1945
                                        FRAB <= DEST_ADDR;
1946
                                        CPU_STATE := CPU_LDW3;
1947
                                when CPU_LDW3 =>
1948
                                        -- write higher byte to destination operand
1949
                                        DATAWRITE(FRAB,TEMP_DATA);
1950
                                        WR <= '1';
1951
                                        CPU_STATE := CPU_LDW4;
1952
                                when CPU_LDW4 =>
1953
                                        -- points FRAB to lower byte of destination address
1954
                                        FRAB <= FRAB + 1;
1955
                                        CPU_STATE := CPU_LDW5;
1956
                                when CPU_LDW5 =>
1957
                                        DATAWRITE(FRAB,RESULT);
1958
                                        CPU_STATE := CPU_STORE;
1959 2 fabiop
                                when CPU_LDPTOIM =>     -- LOAD PROGRAM TO INDIRECT MEMORY **************************************************************************
1960 3 fabiop
                                        TEMP_DATA := DATAREAD(FRAB);
1961 2 fabiop
                                        DEST_ADDR := RP(3 downto 0) & TEMP_DATA; -- the destination address is read from the indirect address
1962
                                        if (WORD_DATA='1') then
1963
                                                -- it is a LDCI instruction, so we have to increment the indirect address after the operation
1964 3 fabiop
                                                DATAWRITE(FRAB,TEMP_DATA+1);
1965 2 fabiop
                                                WR <= '1';
1966
                                                CPU_STATE := CPU_LDPTOIM2;
1967
                                        else
1968
                                                -- it is a LDC instruction, proceed the load instruction
1969 3 fabiop
                                                FRAB <= ADDRESSER4(RESULT(3 downto 0));          -- the source address (program memory) is read from source register pair
1970 2 fabiop
                                                CPU_STATE := CPU_LDPTOM;
1971
                                        end if;
1972
                                when CPU_LDPTOIM2 =>
1973 3 fabiop
                                        FRAB <= ADDRESSER4(RESULT(3 downto 0));          -- the source address (program memory) is read from source register pair
1974 2 fabiop
                                        CPU_STATE := CPU_LDPTOM;
1975
                                when CPU_LDPTOM =>      -- LOAD PROGRAM TO MEMORY ***********************************************************************************
1976 3 fabiop
                                        IAB(15 downto 8) <= DATAREAD(FRAB);     -- read the high address from the first register
1977
                                        FRAB <= FRAB + 1;
1978 2 fabiop
                                        CPU_STATE := CPU_LDPTOM2;
1979
                                when CPU_LDPTOM2 =>
1980 3 fabiop
                                        IAB(7 downto 0) <= DATAREAD(FRAB);       -- read the low address from the second register
1981
                                        FRAB <= DEST_ADDR;
1982 2 fabiop
                                        if (LU_INSTRUCTION='0') then
1983
                                                CPU_STATE := CPU_LDPTOM3;               -- if it is a read from program memory
1984
                                        else
1985
                                                CPU_STATE := CPU_LDMTOP;                -- if it is a write onto program memory
1986
                                        end if;
1987
                                when CPU_LDPTOM3 =>     -- READ PROGRAM MEMORY AND STORE INTO RAM *******************************************************************
1988 3 fabiop
                                        DATAWRITE(FRAB,IDB);
1989 2 fabiop
                                        WR <= '1';
1990
                                        CAN_FETCH := '1';       -- re-enable fetching
1991
                                        FETCH_ADDR := PC;
1992
                                        IAB <= PC;
1993
                                        CPU_STATE := CPU_DECOD;
1994
                                        if (WORD_DATA='1') then
1995
                                                CPU_STATE := CPU_LDPTOM4;
1996
                                        end if;
1997
                                when CPU_LDPTOM4 =>
1998
                                        DEST_ADDR := ADDRESSER4(RESULT(3 downto 0));
1999 3 fabiop
                                        FRAB <= DEST_ADDR+1;
2000 2 fabiop
                                        TEMP_OP := LU2_INC;
2001
                                        CPU_STATE := CPU_OMA2;
2002
                                when CPU_LDMTOP =>      -- READ RAM AND STORE ONTO PROGRAM MEMORY *******************************************************************
2003 3 fabiop
                                        IWDB <= DATAREAD(FRAB); -- IWDB receive the content of RAM
2004 2 fabiop
                                        PGM_WR <= '1';                  -- enable program memory write signal
2005
                                        CPU_STATE := CPU_LDMTOP2;
2006
                                when CPU_LDMTOP2 =>
2007
                                        CAN_FETCH := '1';               -- re-enable instruction fetching
2008
                                        FETCH_ADDR := PC;
2009
                                        IAB <= PC;
2010
                                        CPU_STATE := CPU_DECOD;
2011
                                        if (WORD_DATA='1') then
2012
                                                CPU_STATE := CPU_LDPTOM4;
2013
                                        end if;
2014 3 fabiop
                                when CPU_BIT =>         -- BIT INSTRUCTION *******************************************************************************************
2015
                                        TEMP_DATA := DATAREAD(FRAB);
2016 2 fabiop
                                        TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0)))):=TEMP_OP(3);
2017 3 fabiop
                                        DATAWRITE(FRAB,TEMP_DATA);
2018 2 fabiop
                                        WR <= '1';
2019
                                        CPU_STATE := CPU_DECOD;
2020 3 fabiop
                                when CPU_IBTJ =>        -- INDIRECT BIT TEST JUMP INSTRUCTION ************************************************************************
2021
                                        FRAB <= RP(3 downto 0) & DATAREAD(FRAB);
2022 2 fabiop
                                        CPU_STATE := CPU_BTJ;
2023 3 fabiop
                                when CPU_BTJ =>         -- BIT TEST JUMP INSTRUCTION *********************************************************************************
2024
                                        TEMP_DATA := DATAREAD(FRAB);
2025 2 fabiop
                                        if (TEMP_DATA(to_integer(unsigned(TEMP_OP(2 downto 0))))=TEMP_OP(3)) then
2026
                                                PC := ADDER16(PC,RESULT);
2027
                                                IQUEUE.FETCH_STATE := F_ADDR;
2028
                                        end if;
2029
                                        CPU_STATE := CPU_DECOD;
2030 3 fabiop
                                when CPU_DJNZ =>        -- DECREMENT AND JUMP IF NOT ZERO INSTRUCTION ****************************************************************
2031
                                        RESULT := LU2(LU2_DEC,DATAREAD(FRAB),'0','0','0');
2032 2 fabiop
                                        if (ALU_FLAGS.Z='0') then        -- result is not zero, then jump relative
2033
                                                PC := DEST_ADDR16;
2034
                                                IQUEUE.FETCH_STATE := F_ADDR;
2035
                                        end if;
2036 3 fabiop
                                        DATAWRITE(FRAB,RESULT);
2037 2 fabiop
                                        WR <= '1';
2038
                                        CPU_STATE := CPU_DECOD;
2039 3 fabiop
                                when CPU_INDJUMP =>     -- INDIRECT JUMP INSTRUCTION *********************************************************************************
2040
                                        PC(15 downto 8) := DATAREAD(FRAB);
2041
                                        FRAB <= FRAB + 1;
2042 2 fabiop
                                        CPU_STATE:= CPU_INDJUMP2;
2043
                                when CPU_INDJUMP2 =>
2044 3 fabiop
                                        PC(7 downto 0) := DATAREAD(FRAB);
2045 2 fabiop
                                        IQUEUE.FETCH_STATE := F_ADDR;
2046
                                        CPU_STATE := CPU_DECOD;
2047 3 fabiop
                                when CPU_TRAP =>        -- TRAP INSTRUCTION ******************************************************************************************
2048
                                        PC(15 downto 8) := DATAREAD(FRAB);
2049
                                        FRAB <= FRAB + 1;
2050 2 fabiop
                                        CPU_STATE:= CPU_TRAP2;
2051
                                when CPU_TRAP2 =>
2052 3 fabiop
                                        PC(7 downto 0) := DATAREAD(FRAB);
2053 2 fabiop
                                        SP := SP - 1;
2054 3 fabiop
                                        FRAB <= SP;
2055 2 fabiop
                                        IQUEUE.FETCH_STATE := F_ADDR;
2056
                                        LU_INSTRUCTION := '1';
2057
                                        CPU_STATE := CPU_STACK;
2058 3 fabiop
                                when CPU_INDSTACK =>    -- INDIRECT CALL INSTRUCTION *****************************************************************************
2059
                                        PC(15 downto 8) := DATAREAD(FRAB);
2060
                                        FRAB <= FRAB + 1;
2061 2 fabiop
                                        CPU_STATE:= CPU_INDSTACK2;
2062
                                when CPU_INDSTACK2 =>
2063 3 fabiop
                                        PC(7 downto 0) := DATAREAD(FRAB);
2064 2 fabiop
                                        SP := SP - 1;
2065 3 fabiop
                                        FRAB <= SP;
2066 2 fabiop
                                        IQUEUE.FETCH_STATE := F_ADDR;
2067
                                        CPU_STATE := CPU_STACK;
2068 3 fabiop
                                when CPU_VECTOR =>              -- LOAD PC WITH ADDRESS STORED IN PROGRAM MEMORY *********************************************************
2069
                                        PC(15 downto 8) := IDB;         -- read high byte of destination address
2070 2 fabiop
                                        IAB <= IAB + 1;
2071
                                        CPU_STATE := CPU_VECTOR2;
2072
                                when CPU_VECTOR2 =>
2073 3 fabiop
                                        PC(7 downto 0) := IDB;           -- read low byte of destination address
2074
                                        IQUEUE.FETCH_STATE := F_ADDR;   -- reset queue FSM
2075
                                        CAN_FETCH := '1';                               -- restart fetching
2076
                                        if (INT_FLAG='1') then CPU_STATE := CPU_STACK;
2077 2 fabiop
                                        else CPU_STATE := CPU_DECOD;
2078
                                        end if;
2079 3 fabiop
                                when CPU_STACK =>       -- PUSH PC 7:0 INTO THE STACK ********************************************************************************
2080
                                        DATAWRITE(FRAB,DEST_ADDR16(7 downto 0));
2081 2 fabiop
                                        WR <= '1';
2082
                                        CPU_STATE := CPU_STACK1;
2083
                                when CPU_STACK1 =>
2084
                                        SP := SP - 1;
2085 3 fabiop
                                        FRAB <= SP;
2086 2 fabiop
                                        CPU_STATE := CPU_STACK2;
2087 3 fabiop
                                when CPU_STACK2 =>      -- PUSH PC 15:8 INTO THE STACK *******************************************************************************
2088
                                        DATAWRITE(FRAB,DEST_ADDR16(15 downto 8));
2089 2 fabiop
                                        WR <= '1';
2090 3 fabiop
                                        if (INT_FLAG='1') then
2091 2 fabiop
                                                CPU_STATE := CPU_STACK3;
2092
                                        else
2093
                                                CPU_STATE := CPU_DECOD;
2094
                                        end if;
2095 3 fabiop
                                when CPU_STACK3 =>      -- PUSH FLAGS INTO THE STACK *********************************************************************************
2096 2 fabiop
                                        SP := SP - 1;
2097 3 fabiop
                                        FRAB <= SP;
2098
                                        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);
2099 2 fabiop
                                        IRQE := '0';
2100 3 fabiop
                                        CPU_STATE := CPU_STORE;
2101
                                when CPU_UNSTACK3 =>    -- POP FLAGS FROM STACK **********************************************************************************
2102
                                        TEMP_DATA := DATAREAD(FRAB);
2103 2 fabiop
                                        CPU_FLAGS.C := TEMP_DATA(7);
2104
                                        CPU_FLAGS.Z := TEMP_DATA(6);
2105
                                        CPU_FLAGS.S := TEMP_DATA(5);
2106
                                        CPU_FLAGS.V := TEMP_DATA(4);
2107
                                        CPU_FLAGS.D := TEMP_DATA(3);
2108
                                        CPU_FLAGS.H := TEMP_DATA(2);
2109
                                        CPU_FLAGS.F2 := TEMP_DATA(1);
2110
                                        CPU_FLAGS.F1 := TEMP_DATA(0);
2111
                                        SP := SP + 1;
2112 3 fabiop
                                        FRAB <= SP;
2113
                                        CPU_STATE := CPU_UNSTACK2;
2114
                                when CPU_UNSTACK2 =>    -- POP PC(15:8) FROM STACK *******************************************************************************
2115
                                        DEST_ADDR16(15 downto 8) := DATAREAD(FRAB);
2116 2 fabiop
                                        SP := SP + 1;
2117 3 fabiop
                                        FRAB <= SP;
2118
                                        CPU_STATE := CPU_UNSTACK;
2119
                                when CPU_UNSTACK =>             -- POP PC(7:0) FROM STACK ********************************************************************************
2120
                                        DEST_ADDR16(7 downto 0) := DATAREAD(FRAB);
2121 2 fabiop
                                        SP := SP + 1;
2122
                                        PC := DEST_ADDR16;
2123
                                        IQUEUE.FETCH_STATE := F_ADDR;
2124
                                        CPU_STATE := CPU_DECOD;
2125 3 fabiop
                                when CPU_STORE =>       -- stores data into memory
2126
                                        WR <= '1';              -- enable write signal (it is automatically disabled on CPU_DECOD state)
2127
                                        CPU_STATE := CPU_DECOD; -- proceed to main decoding state
2128 2 fabiop
                                when CPU_ILLEGAL =>     -- An illegal opcode was fetched 
2129 3 fabiop
                                when CPU_RESET =>               -- SOFTWARE RESET (TRIGGERED BY OCD RESET BIT) ***********************************************************
2130 2 fabiop
                                        IAB <= x"0002";
2131 3 fabiop
                                        FRAB <= x"000";
2132
                                        IWDB <= x"00";
2133 2 fabiop
                                        SP := x"000";
2134
                                        RP := x"00";
2135
                                        WR <= '0';
2136
                                        PGM_WR <= '0';
2137
                                        STOP <= '0';
2138
                                        CAN_FETCH := '1';
2139
                                        FETCH_ADDR := x"0000";
2140
                                        RXSYNC1 <= '1';
2141
                                        RXSYNC2 <= '1';
2142
                                        DBG_UART.LAST_SMP := '1';
2143
                                        IQUEUE.FETCH_STATE := F_ADDR;
2144
                                        IRQE := '0';
2145
                                        IRQ0 := x"00";
2146
                                        OLD_IRQ0 := x"00";
2147
                                        IRQ0ENH := x"00";
2148
                                        IRQ0ENL := x"00";
2149
                                        OCDCR.RST := '0';
2150
                                        ATM_COUNTER := 0;
2151
                                        CPU_STATE := CPU_VECTOR;
2152
                                when others =>
2153
                                        CPU_STATE := CPU_DECOD;
2154 3 fabiop
                        end case;
2155
                        -- end of the main decoder
2156 2 fabiop
                end if;
2157
        end process;
2158
end CPU;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.