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

Subversion Repositories nextz80

[/] [nextz80/] [trunk/] [Next8080CPU.v] - Blame information for rev 18

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next8080 project
4
//
5
// Filename: Next8080CPU.v
6
// Description: Implementation of 8080 compatible CPU
7
// Version 1.0
8
// Creation date: 28Jan2018
9
//
10
// Author: Nicolae Dumitrache 
11
// e-mail: ndumitrache@opencores.org
12
//
13
/////////////////////////////////////////////////////////////////////////////////
14
// 
15
// Copyright (C) 2018 Nicolae Dumitrache
16
// 
17
// This source file may be used and distributed without 
18
// restriction provided that this copyright statement is not 
19
// removed from the file and that any derivative work contains 
20
// the original copyright notice and the associated disclaimer.
21
// 
22
// This source file is free software; you can redistribute it 
23
// and/or modify it under the terms of the GNU Lesser General 
24
// Public License as published by the Free Software Foundation;
25
// either version 2.1 of the License, or (at your option) any 
26
// later version. 
27
// 
28
// This source is distributed in the hope that it will be 
29
// useful, but WITHOUT ANY WARRANTY; without even the implied 
30
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
31
// PURPOSE. See the GNU Lesser General Public License for more 
32
// details. 
33
// 
34
// You should have received a copy of the GNU Lesser General 
35
// Public License along with this source; if not, download it 
36
// from http://www.opencores.org/lgpl.shtml 
37
// 
38
///////////////////////////////////////////////////////////////////////////////////
39
//
40
// Comments:
41
//
42
//      Next8080 processor features:
43
//              Fast conditional jump/call/ret takes only 1 T state if not executed
44
//              Each CPU machine cycle takes (mainly) one clock T state. This makes this processor over 4 times faster than a 8080 at the same 
45
//                      clock frequency (some instructions are up to 10 times faster). 
46
// Only 8080 instructions available (minus DAA, which = CPL) + some extra: JR, DJNZ
47 17 ndumitrach
// Only IM0 supported, flags 3 and 5 always 0, opcodes ED, FD, CB treated as NOP
48 14 ndumitrach
// No H and N flags, always 0
49 17 ndumitrach
 
50
// Indexed mode: after the new instruction INDEX i8 [0xdd, i8], the next instruction (only) will use (mem+i8) instead of (mem)
51
// No interrupt is accepted after INDEX i8. i8 is a signed 8bit value.
52
// Indexed mode applies to the following instructions: 
53
//              02h = ld (bc+i8),a 
54
//              12h = ld (de+i8),a
55
//              22h = ld (hl+i8),a instead of ld (nn),hl. Ex: [0xdd 0xff 0x22] will execute ld (hl-1),a
56
//              32h = ld (sp+i8),a instead of ld (nn),a.  Ex: [0xdd 0x13 0x32] will execute ld (sp+13h),a
57
//              0Ah = ld a,(bc+i8)
58
//              1Ah = ld a,(de+i8)
59
//              2Ah = ld a,(hl+i8),a instead of ld hl,(nn)
60
//              3Ah = ld a,(sp+i8),a instead of ld a,(nn)
61
//      All the other instructions which uses memory at (hl): ld r,(hl+i8); ld (hl+i8),r; inc (hl+i8); dec (hl+i8); ld (hl+i8),n; op a,(hl);
62
 
63 14 ndumitrach
// ~450 LUT6
64
// See NextZ80 for more detais
65
///////////////////////////////////////////////////////////////////////////////////
66
 
67
`timescale 1ns / 1ps
68
 
69
module Next8080
70
(
71
                input CLK,
72
                input RESET,
73
                input INT,
74
                input WAIT,
75
                input [7:0]DI,
76
 
77
                output [7:0]DO,
78
                output [15:0]ADDR,
79
                output reg WR,
80
                output reg MREQ,
81
                output reg IORQ,
82
                output reg HALT,
83
                output reg M1
84
);
85
 
86
// connections and registers
87 18 ndumitrach
        reg     [2:0] CPUStatus = 0;      // 0=HL-DE, 1=EI, 2-indexed mode 
88 14 ndumitrach
        wire    [7:0] ALU8FLAGS;
89
        wire    [7:0] FLAGS;
90
        wire    [7:0] ALU80;
91
        wire    [7:0] ALU81;
92
        wire    [15:0]ALU160;
93
        wire    [7:0] ALU161;
94
        wire    [15:0]ALU8OUT;
95
 
96
        reg     [8:0]    FETCH = 0;
97
        reg     [2:0]    STAGE = 0;
98
        wire    [5:0]    opd;
99
        wire    [2:0] op16;
100
        wire    op0mem = FETCH[2:0] == 6;
101
        wire    op1mem = FETCH[5:3] == 6;
102
 
103
// stage status
104
        reg     [1:0]DO_SEL;                     // ALU80 - th - flags - ALU8OUT[7:0]
105
        reg     ALU160_SEL;                             // regs - pc
106
        reg     DINW_SEL;                               // ALU8OUT - DI
107
        reg     [5:0]WE;                 // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
108
        reg     [4:0] ALU8OP;
109
        reg     [2:0] ALU16OP;
110
        reg     next_stage;
111
        reg     [3:0]REG_WSEL;
112
        reg     [3:0]REG_RSEL;
113 17 ndumitrach
        reg     [3:0]status;                     // 0=HL-DE, 1=EI, 2=set EI, 3=set indexed mode
114 14 ndumitrach
// FETCH[5:3]: 000 NZ, 001 Z, 010 NC, 011 C, 100 PO, 101 PE, 110 P, 111 M
115
        wire    [7:0]FlagMux = {FLAGS[7], !FLAGS[7], FLAGS[2], !FLAGS[2], FLAGS[0], !FLAGS[0], FLAGS[6], !FLAGS[6]};
116
        reg     tzf;
117
        reg     SRESET = 0;
118
        reg     SINT = 0;
119
 
120 18 ndumitrach
        N8080_Reg CPU_REGS (
121 14 ndumitrach
                 .rstatus(CPUStatus[0]),
122
                 .M1(M1),
123
                 .WE(WE),
124
                 .CLK(CLK),
125
                 .ALU8OUT(ALU8OUT),
126
                 .DI(DI),
127
                 .DO(DO),
128
                 .ADDR(ADDR),
129
                 .CONST({2'b00, FETCH[5:3], 3'b000}),   // RST address
130
                 .ALU80(ALU80),
131
                 .ALU81(ALU81),
132
                 .ALU160(ALU160),
133
                 .ALU161(ALU161),
134
                 .ALU8FLAGS(ALU8FLAGS),
135
                 .FLAGS(FLAGS),
136
                 .DO_SEL(DO_SEL),
137
                 .ALU160_sel(ALU160_SEL),
138
                 .REG_WSEL(REG_WSEL),
139
                 .REG_RSEL(REG_RSEL),
140
                 .DINW_SEL(DINW_SEL),
141
                 .ALU16OP(ALU16OP),                     // used for post increment for ADDR, SP mux re-direct
142
                 .WAIT(WAIT)
143
                 );
144
 
145 18 ndumitrach
        N8080_ALU8 CPU_ALU8 (
146 14 ndumitrach
                 .D0(ALU80),
147
                 .D1(ALU81),
148
                 .FIN(FLAGS),
149
                 .FOUT(ALU8FLAGS),
150
                 .ALU8DOUT(ALU8OUT),
151
                 .OP(ALU8OP)
152
                 );
153
 
154 18 ndumitrach
        N8080_ALU16 CPU_ALU16 (
155 14 ndumitrach
                 .D0(ALU160),
156
                 .D1(ALU161),
157
                 .DOUT(ADDR),
158
                 .OP(ALU16OP)
159
                 );
160
 
161
        always @(posedge CLK)
162
                if(!WAIT) begin
163
                        SRESET <= RESET;
164
                        SINT <= INT;
165
                        if(SRESET) FETCH <= 9'b110000000;
166
                        else
167
                                if(FETCH[8:6] == 3'b110) {FETCH[8:7]} <= 2'b00; // exit RESET state
168
                                else begin
169
                                        if(M1) FETCH <= {1'b0, DI};
170 17 ndumitrach
                                        if(!next_stage & SINT & CPUStatus[1] & !status[2] & !status[3]) {FETCH[8:6], FETCH[1:0]} <= {3'b100, HALT, M1};  // INT request
171 14 ndumitrach
                                end
172
                        if(next_stage) STAGE <= STAGE + 1'b1;
173
                        else STAGE <= 0;
174
                        CPUStatus[0] <= CPUStatus[0] ^ status[0];
175
                        if(status[2]) CPUStatus[1] <= status[1];        // EI
176 17 ndumitrach
                        if(!next_stage) CPUStatus[2] <= status[3];
177 14 ndumitrach
                        tzf <= ALU8FLAGS[6];
178
                end
179
 
180
        assign opd[0] = FETCH[0] ^ &FETCH[2:1];
181
        assign opd[2:1] = FETCH[2:1];
182
        assign opd[3] = FETCH[3] ^ &FETCH[5:4];
183
        assign opd[5:4] = FETCH[5:4];
184
        assign op16[2:0] = &FETCH[5:4] ? 3'b101 : {1'b0, FETCH[5:4]};
185
 
186
        always @* begin
187
                DO_SEL  = 2'bxx;                                        // ALU80 - th - flags - ALU8OUT[7:0]
188
                ALU160_SEL = 1'bx;                                      // regs - pc
189
                DINW_SEL = 1'bx;                                        // ALU8OUT - DI
190
                WE              = 6'bxxxxxx;                            // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
191
                ALU8OP  = 5'bxxxxx;
192
                ALU16OP = 3'b000;                                       // NOP, post inc
193
                next_stage = 0;
194
                REG_WSEL        = 4'bxxxx;
195
                REG_RSEL        = 4'bx0xx;                              // prevents default 4'b0100 which leads to incorrect P flag value in some cases (like RLA)
196
                M1              = 1;
197
                MREQ    = 1;
198
                WR              = 0;
199
                HALT = 0;
200
                IORQ = 0;
201 17 ndumitrach
                status  = 4'b0000;
202 14 ndumitrach
 
203
 
204
                case(FETCH[8:6])
205
//------------------------------------------- block 00 ----------------------------------------------------
206
                        3'b000:
207
                                case(FETCH[3:0])
208
//                              -----------------------         NOP, EX AF, AF', DJNZ, JR, JR c --------------------
209
                                        4'b0000, 4'b1000:
210
                                                case(FETCH[5:4])
211
                                                        2'b00: begin                                    // NOP, EX AF, AF'
212
                                                                ALU160_SEL = 1;                 // PC
213
                                                                WE              = 6'b010x00;    // PC
214
                                                        end
215
                                                        2'b01:
216
                                                                if(!STAGE[0]) begin              // DJNZ, JR - stage1
217
                                                                        ALU160_SEL = 1;                 // pc
218
                                                                        WE              = 6'b010100;    // PC, tmpHI
219
                                                                        ALU8OP  = 5'b01010;             // DEC, for tzf only
220
                                                                        REG_WSEL        = 4'b0000;      // B
221
                                                                        next_stage = 1;
222
                                                                        M1              = 0;
223
                                                                end else if(FETCH[3]) begin     // JR - stage2
224
                                                                        ALU160_SEL = 1;                 // pc
225
                                                                        WE              = 6'b010x00;    // PC
226
                                                                        ALU16OP = 3;                    // ADD
227
                                                                end else begin                          // DJNZ - stage2
228
                                                                        ALU160_SEL = 1;                 // pc
229
                                                                        DINW_SEL = 0;                    // ALU8OUT
230
                                                                        WE              = 6'b010x10;    // PC, hi
231
                                                                        ALU8OP  = 5'b01010;             // DEC
232
                                                                        ALU16OP = tzf ? 3'd0 : 3'd3;    // NOP/ADD
233
                                                                        REG_WSEL        = 4'b0000;                      // B
234
                                                                end
235
                                                        2'b10, 2'b11:                                                   // JR cc, stage1, stage2
236
                                                                case({STAGE[0], FlagMux[{1'b0, FETCH[4:3]}]})
237
                                                                        2'b00, 2'b11: begin
238
                                                                                ALU160_SEL = 1;                         // pc
239
                                                                                WE              = 6'b010x00;            // PC
240
                                                                                ALU16OP = STAGE[0] ? 3'd3 : 3'd1;                // ADD/ INC, post inc
241
                                                                        end
242
                                                                        2'b01: begin
243
                                                                                ALU160_SEL = 1;                         // pc
244
                                                                                WE              = 6'b010100;            // PC, tmpHI
245
                                                                                next_stage = 1;
246
                                                                                M1              = 0;
247
                                                                        end
248
                                                                endcase
249
                                                endcase
250
//                              -----------------------         LD rr,nn  --------------------
251
                                        4'b0001:                        // LD rr,nn, stage1
252
                                                case({STAGE[1:0], op16[2]})
253
                                                        3'b00_0, 3'b00_1, 3'b01_0, 3'b01_1: begin                       // LD rr,nn, stage1,2
254
                                                                ALU160_SEL = 1;                 // pc
255
                                                                DINW_SEL = 1;                           // DI
256
                                                                WE              = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};   // PC, lo/HI
257
                                                                next_stage = 1;
258
                                                                REG_WSEL        = {op16, 1'bx};
259
                                                                M1              = 0;
260
                                                        end
261
                                                        3'b10_0, 3'b11_1: begin         // BC, DE, HL, stage3, SP stage4
262
                                                                ALU160_SEL = 1;                 // pc
263
                                                                WE              = 6'b010x00;    // PC
264
                                                        end
265
                                                        3'b10_1: begin                          // SP stage3
266
                                                                ALU160_SEL = 0;                  // regs
267
                                                                WE              = 6'b001x00;    // SP
268
                                                                ALU16OP = 4;                            // NOP
269
                                                                next_stage = 1;
270
                                                                REG_RSEL        = 4'b101x;              // tmpSP
271
                                                                M1              = 0;
272
                                                                MREQ            = 0;
273
                                                        end
274
                                                endcase
275
//                              -----------------------         LD (BC) A -  LD (DE) A - LD (nn) HL, LD (nn),A   --------------------
276
//                              -----------------------         LD A (BC) -  LD A (DE) - LD HL (nn), LD A (nn)   --------------------
277
                                        4'b0010,        4'b1010:
278
                                                case(STAGE[2:0])
279
                                                        3'b000:
280 17 ndumitrach
                                                                if(!FETCH[5] | CPUStatus[2]) begin                      // LD (BC) A, LD (DE) A - stage1
281
                                                                        DINW_SEL = 1;   // DI
282
                                                                        DO_SEL  = 2'b00;                // ALU80
283 14 ndumitrach
                                                                        ALU160_SEL = 0;                          // regs
284 17 ndumitrach
                                                                        if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
285 14 ndumitrach
                                                                        WE              = {4'b000x, FETCH[3], 1'bx};            // hi
286
                                                                        next_stage = 1;
287
                                                                        REG_WSEL        = FETCH[3] ? 4'b011x : 4'b0110; // A
288
                                                                        REG_RSEL        = {op16, 1'bx};
289
                                                                        M1              = 0;
290
                                                                        WR = !FETCH[3];
291
                                                                end else begin                                  // LD (nn) A - LD (nn) HL - stage 1
292
                                                                        ALU160_SEL = 1;                         // PC
293
                                                                        DINW_SEL = 1;                                   // DI
294
                                                                        WE              = 6'b010xx1;            // PC, lo
295
                                                                        next_stage = 1;
296
                                                                        REG_WSEL        = 4'b111x;
297
                                                                        M1              = 0;
298
                                                                end
299
                                                        3'b001:
300 17 ndumitrach
                                                                if(!FETCH[5] | CPUStatus[2]) begin                      // LD (BC), A, LD (DE), A - stage2
301 14 ndumitrach
                                                                        ALU160_SEL = 1;                         // pc
302
                                                                        WE              = 6'b010x00;            // PC
303
                                                                end else begin                                          // LD (nn),A  - LH (nn),HL - stage 2
304
                                                                        ALU160_SEL = 1;                         // pc
305
                                                                        DINW_SEL = 1;                                   // DI
306
                                                                        WE              = 6'b010x10;            // PC, hi
307
                                                                        next_stage = 1;
308
                                                                        REG_WSEL        = 4'b111x;
309
                                                                        M1              = 0;
310
                                                                end
311
                                                        3'b010: begin
312
                                                                ALU160_SEL = 1'b0;              // regs
313
                                                                REG_RSEL        = 4'b111x;
314
                                                                M1              = 0;
315
                                                                WR                      = !FETCH[3];
316
                                                                next_stage = 1;
317
                                                                if(FETCH[3]) begin              // LD A (nn)  - LD HL (nn) - stage 3
318
                                                                        DINW_SEL = 1;                           // DI
319
                                                                        WE              = {4'b000x, FETCH[4] ? 1'b1 : 1'bx, FETCH[4] ? 1'bx : 1'b1};    // lo/hi
320
                                                                        REG_WSEL = FETCH[4] ? 4'b011x : 4'b010x;        // A or L
321
                                                                end else begin                          // LD (nn),A  - LD (nn),HL - stage 3
322
                                                                        DO_SEL  = 2'b00;                        // ALU80
323
                                                                        WE              = 6'b000x00;    // nothing
324
                                                                        REG_WSEL = FETCH[4] ? 4'b0110 : 4'b0101;        // A or L
325
                                                                end
326
                                                        end
327
                                                        3'b011:
328
                                                                if(FETCH[4]) begin                      // LD (nn),A - stage 4
329
                                                                        ALU160_SEL = 1;                 // pc
330
                                                                        WE              = 6'b010x00;    // PC
331
                                                                end else begin
332
                                                                        REG_RSEL        = 4'b111x;
333
                                                                        M1              = 0;
334
                                                                        WR                      = !FETCH[3];
335
                                                                        ALU160_SEL = 1'b0;              // regs
336
                                                                        ALU16OP = 1;                            // INC
337
                                                                        next_stage = 1;
338
                                                                        if(FETCH[3]) begin      // LD HL (nn) - stage 4
339
                                                                                DINW_SEL = 1;                           // DI
340
                                                                                WE              = 6'b000x10;    // hi
341
                                                                                REG_WSEL = 4'b010x;             // H
342
                                                                        end else begin                  // LD (nn),HL - stage 4
343
                                                                                DO_SEL  = 2'b00;                        // ALU80
344
                                                                                WE              = 6'b000x00;    // nothing
345
                                                                                REG_WSEL = 4'b0100;             // H
346
                                                                        end
347
                                                                end
348
                                                        3'b100: begin                           // LD (nn),HL - stage 5
349
                                                                ALU160_SEL = 1;                 // pc
350
                                                                WE              = 6'b010x00;    // PC
351
                                                        end
352
                                                endcase
353
//                              -----------------------         inc/dec rr   --------------------
354
                                        4'b0011, 4'b1011:
355
                                                if(!STAGE[0])
356
                                                        if(op16[2]) begin                       // SP - stage1
357
                                                                ALU160_SEL = 0;                  // regs
358
                                                                WE              = 6'b001x00;    // SP
359
                                                                ALU16OP = {FETCH[3], 1'b0, FETCH[3]};           // post inc, dec
360
                                                                next_stage = 1;
361
                                                                REG_RSEL        = 4'b101x;      // sp
362
                                                                M1              = 0;
363
                                                                MREQ            = 0;
364
                                                        end else begin                          // BC, DE, HL - stage 1
365
                                                                ALU160_SEL = 1;                 // pc
366
                                                                DINW_SEL = 0;                    // ALU8OUT
367
                                                                WE              = 6'b010x11;    // PC, hi, lo
368
                                                                ALU8OP  = {4'b0111, FETCH[3]};                  // INC16 / DEC16
369
                                                                REG_WSEL        = {op16, 1'b0}; // hi
370
                                                                REG_RSEL        = {op16, 1'b1}; // lo
371
                                                        end
372
                                                else    begin                           // SP, stage2
373
                                                        ALU160_SEL = 1;                 // pc
374
                                                        WE              = 6'b010x00;    // PC
375
                                                end
376
//                              -----------------------         inc/dec 8  --------------------
377
                                        4'b0100, 4'b0101, 4'b1100, 4'b1101:
378
                                                if(!op1mem) begin                                               //regs
379
                                                        DINW_SEL = 0;                                            // ALU8OUT
380
                                                        ALU160_SEL = 1;                                 // pc
381
                                                        WE              = opd[3] ? 6'b110x01 : 6'b110x10;       // flags, PC, hi/lo
382
                                                        ALU8OP  = {3'b010, FETCH[0], 1'b0};              // inc / dec
383
                                                        REG_WSEL        = {1'b0, opd[5:3]};
384
                                                end else case({STAGE[1:0]})
385
                                                        2'b00: begin                            // (HL) - stage1
386
                                                                ALU160_SEL = 0;                                  // regs
387 17 ndumitrach
                                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
388 14 ndumitrach
                                                                DINW_SEL = 1;                                   // DI
389
                                                                WE              = 6'b000001;                    // lo
390
                                                                next_stage = 1;
391
                                                                REG_WSEL        = 4'b011x;                      // tmpLO
392
                                                                REG_RSEL        = 4'b010x;                      // HL
393
                                                                M1              = 0;
394
                                                        end
395
                                                        2'b01: begin                                    // (HL) stage2
396
                                                                DO_SEL  = 2'b11;                        // ALU80OUT
397
                                                                ALU160_SEL = 0;                          // regs
398 17 ndumitrach
                                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
399 14 ndumitrach
                                                                WE              = 6'b100x0x;            // flags
400
                                                                ALU8OP  = {3'b010, FETCH[0], 1'b0};              // inc / dec
401
                                                                next_stage = 1;
402
                                                                REG_WSEL        = 4'b0111;                                      // tmpLO
403
                                                                REG_RSEL        = 4'b010x;                                      // HL
404
                                                                M1              = 0;
405
                                                                WR                      = 1;
406
                                                        end
407
                                                        2'b10: begin                                    // (HL) - stage3
408
                                                                ALU160_SEL = 1;                                         // pc
409
                                                                WE              = 6'b010x00;                            // PC
410
                                                        end
411
                                                endcase
412
//                              -----------------------         ld r/(HL), n  --------------------                                              
413 17 ndumitrach
                                        4'b0110, 4'b1110:
414 14 ndumitrach
                                                case({STAGE[1:0], op1mem})
415
                                                        3'b00_0, 3'b00_1: begin         // r, (HL) - stage1 (read n)
416
                                                                ALU160_SEL = 1;                 // pc
417
                                                                DINW_SEL = 1;                   // DI
418
                                                                WE              = opd[3] ? 6'b010001 : 6'b010010;                       // PC, hi/lo
419
                                                                next_stage = 1;
420
                                                                REG_WSEL        = {1'b0, opd[5:4], 1'bx};
421
                                                                M1              = 0;
422
                                                        end
423
                                                        3'b01_0, 3'b10_1: begin         // r - stage2, (HL) - stage3
424
                                                                ALU160_SEL = 1;                 // pc
425
                                                                WE              = 6'b010x00;    // PC
426
                                                        end
427
                                                        3'b01_1: begin                          // (HL) - stage2
428
                                                                DO_SEL  = 2'b00;                // ALU80
429
                                                                ALU160_SEL = 0;                  // regs
430 17 ndumitrach
                                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
431 14 ndumitrach
                                                                WE              = 6'b000x0x;    // nothing
432
                                                                next_stage = 1;
433
                                                                REG_WSEL        = 4'b0111;      // tmpLO
434
                                                                REG_RSEL        = 4'b010x;      // HL
435
                                                                M1              = 0;
436
                                                                WR                      = 1;
437
                                                        end
438
                                                endcase
439
//                              -----------------------         rlca, rrca, rla, rra, daa, cpl, scf, ccf  --------------------                                          
440
                                        4'b0111, 4'b1111:
441
                                                case(FETCH[5:3])
442
                                                        3'b000, 3'b001, 3'b010, 3'b011, 3'b100, 3'b101: begin           // rlca, rrca, rla, rra, daa, cpl
443
                                                                ALU160_SEL = 1;                                 // pc
444
                                                                DINW_SEL = 0;                                    // ALU8OUT
445
                                                                WE              = 6'b110x1x;                    // flags, PC, hi
446
                                                                ALU8OP  = FETCH[5] ? {2'b01, !FETCH[3], 2'b01} : {3'b110, FETCH[4:3]};
447
                                                                REG_WSEL        = 4'b0110;                      // A
448
                                                        end
449
                                                        3'b110, 3'b111: begin                           // scf, ccf
450
                                                                ALU160_SEL = 1;                                 // pc
451
                                                                DINW_SEL = 0;                                    // ALU8OUT
452
                                                                WE              = 6'b110x0x;                    // flags, PC
453
                                                                ALU8OP  = {4'b1010, !FETCH[3]};
454
                                                        end
455
                                                endcase
456
//                              -----------------------         add 16  --------------------                                            
457
                                        4'b1001:
458
                                                if(!STAGE[0]) begin
459
                                                        DINW_SEL = 0;                                    // ALU8OUT
460
                                                        WE              = 6'b100x01;                    // flags, lo
461
                                                        ALU8OP  = 5'b10000;                             // ADD16LO
462
                                                        next_stage = 1;
463
                                                        REG_WSEL        = 4'b0101;                      // L
464
                                                        REG_RSEL        = {op16, 1'b1};
465
                                                        M1              = 0;
466
                                                        MREQ            = 0;
467
                                                end else begin
468
                                                        ALU160_SEL = 1;                                 // pc
469
                                                        DINW_SEL = 0;                                    // ALU8OUT
470
                                                        WE              = 6'b110x10;                    // flags, PC, hi
471
                                                        ALU8OP  = 5'b10001;                             // ADD16HI
472
                                                        REG_WSEL        = 4'b0100;                      // H
473
                                                        REG_RSEL        = {op16, 1'b0};
474
                                                end
475
                                endcase
476
 
477
// ---------------------------------------------- block 01 LD8 ---------------------------------------------------
478 17 ndumitrach
                        3'b001:
479 14 ndumitrach
                                case({STAGE[0], op1mem, op0mem})
480
                                        3'b0_00,                                        // LD r, r 1st stage
481
                                        3'b1_01:                                        // LD r, (HL) 2nd stage
482
                                        begin
483
                                                ALU160_SEL = 1;                 // PC
484
                                                DINW_SEL          = 0;           // ALU8
485
                                                WE = opd[3] ? 6'b010x01 : 6'b010x10;    // PC and LO or HI
486
                                                ALU8OP = 29;            // PASS D1
487
                                                REG_WSEL = {1'b0, opd[5:4], 1'bx};
488
                                                REG_RSEL = {1'b0, opd[2:0]};
489
                                        end
490
                                        3'b0_01:                                        // LD r, (HL) 1st stage
491
                                        begin
492
                                                ALU160_SEL = 0;                  // regs
493 17 ndumitrach
                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
494 14 ndumitrach
                                                DINW_SEL = 1;                   // DI           
495
                                                WE              = 6'b000x01;    // LO
496
                                                next_stage = 1;
497
                                                REG_WSEL        = 4'b011x;      // A - tmpLO
498
                                                REG_RSEL = 4'b010x;             // HL
499
                                                M1 = 0;
500
                                        end
501
                                        3'b0_10:                                        // LD (HL), r 1st stage
502
                                        begin
503
                                                DO_SEL  = 0;                     // ALU80
504
                                                ALU160_SEL = 0;                  // regs
505 17 ndumitrach
                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
506 14 ndumitrach
                                                WE              = 6'b000x00;    // no write
507
                                                next_stage = 1;
508
                                                REG_WSEL        = {1'b0, opd[2:0]};
509
                                                REG_RSEL        = 4'b010x;      // HL
510
                                                M1              = 0;
511
                                                WR                      = 1;
512
                                        end
513
                                        3'b1_10:                                        // LD (HL), r 2nd stage
514
                                        begin
515
                                                ALU160_SEL = 1;                 // pc
516
                                                WE              = 6'b010x00;    // PC
517
                                        end
518
                                        3'b0_11: begin                          // HALT
519
                                                WE              = 6'b000x00;    // no write
520
                                                M1              = 0;
521
                                                MREQ            = 0;
522
                                                HALT            = 1;
523
                                        end
524
                                endcase
525
// ---------------------------------------------- block 10 arith8 ---------------------------------------------------
526 17 ndumitrach
                        3'b010:
527 14 ndumitrach
                                case({STAGE[0], op0mem})
528
                                        2'b0_0,                                 // OP r,r 1st stage
529
                                        2'b1_1:                                 // OP r, (HL) 2nd stage
530
                                        begin
531
                                                ALU160_SEL = 1;                 // pc
532
                                                DINW_SEL = 0;                    // ALU8OUT
533
                                                WE              = {4'b110x, ~&FETCH[5:3], 1'bx};        // flags, PC, hi
534
                                                ALU8OP  = {2'b00, FETCH[5:3]};
535
                                                REG_WSEL        = 4'b0110;      // A
536
                                                REG_RSEL        = {1'b0, opd[2:0]};
537
                                        end
538
                                        2'b0_1:                                 // OP r, (HL) 1st stage
539
                                        begin
540 17 ndumitrach
                                                ALU160_SEL = 0;                  // regs
541
                                                if(CPUStatus[2]) ALU16OP = 3;                                   // indexed mode
542 14 ndumitrach
                                                DINW_SEL = 1;                   // DI
543
                                                WE              = 6'b000x01;    // lo
544
                                                next_stage = 1;
545
                                                REG_WSEL        = 4'b011x;      // A-tmpLO
546
                                                REG_RSEL        = 4'b010x;      // HL
547
                                                M1              = 0;
548
                                        end
549
                                endcase
550
//------------------------------------------- block 11 ----------------------------------------------------
551
                        3'b011:
552
                                case(FETCH[3:0])
553
//                              -----------------------         RET cc --------------------
554
                                        4'b0000, 4'b1000:
555
                                                case(STAGE[1:0])
556
                                                        2'b00, 2'b01:                   // stage1, stage2
557
                                                                if(FlagMux[FETCH[5:3]]) begin   // POP addr
558
                                                                        ALU160_SEL = 0;                          // regs
559
                                                                        DINW_SEL = 1;                                   // DI
560
                                                                        WE              = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // SP, lo/hi
561
                                                                        next_stage = 1;
562
                                                                        REG_WSEL        = 4'b111x;                      // tmp16
563
                                                                        REG_RSEL        = 4'b101x;                      // SP
564
                                                                        M1              = 0;
565
                                                                end else begin
566
                                                                        ALU160_SEL = 1;                         // pc
567
                                                                        WE              = 6'b010x00;            // PC
568
                                                                end
569
                                                        2'b10: begin                    // stage3
570
                                                                ALU160_SEL = 0;                                  // regs
571
                                                                WE              = 6'b010x00;                    // PC
572
                                                                REG_RSEL        = 4'b111x;                              // tmp16
573
                                                        end
574
                                                endcase
575
//                              -----------------------         POP --------------------
576
                                        4'b0001:
577
                                                case(STAGE[1:0])
578
                                                        2'b00, 2'b01: begin
579
                                                                if(op16[2]) begin       // AF
580
                                                                        WE              = STAGE[0] ? 6'b101x1x : 6'b001xx1;              // flags, SP, lo/hi
581
                                                                        REG_WSEL        = {3'b011, STAGE[0] ? 1'b1 : 1'bx};
582
                                                                        if(STAGE[0]) ALU8OP      = 30;                                           // FLAGS <- D0
583
                                                                end else begin          // r16
584
                                                                        WE              = STAGE[0] ? 6'b001x10 : 6'b001xx1;              // SP, lo/hi
585
                                                                        REG_WSEL        = {1'b0, FETCH[5:4], 1'bx};
586
                                                                end
587
                                                                ALU160_SEL = 0;                  // regs
588
                                                                DINW_SEL = 1;                           // DI
589
                                                                next_stage = 1;
590
                                                                REG_RSEL        = 4'b101x;              // SP
591
                                                                M1              = 0;
592
                                                        end
593
                                                        2'b10: begin                                    // stage3
594
                                                                ALU160_SEL = 1;                 // PC
595
                                                                WE              = 6'b010x00;    // PC
596
                                                        end
597
                                                endcase
598
//                              -----------------------         JP cc --------------------
599
                                        4'b0010, 4'b1010:
600
                                                case(STAGE[1:0])
601
                                                        2'b00, 2'b01:   begin                           // stage1,2
602
                                                                if(FlagMux[FETCH[5:3]]) begin
603
                                                                        ALU160_SEL = 1;                                 // pc
604
                                                                        DINW_SEL = 1;                                           // DI
605
                                                                        WE              = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // PC, hi/lo
606
                                                                        next_stage = 1;
607
                                                                        REG_WSEL        = 4'b111x;                              // tmp7
608
                                                                        M1              = 0;
609
                                                                end else begin
610
                                                                        ALU160_SEL = 1;                                 // pc
611
                                                                        WE              = 6'b010x00;                    // PC
612
                                                                        ALU16OP = 2;                                            // add2
613
                                                                end
614
                                                        end
615
                                                        2'b10: begin                                            // stage3
616
                                                                ALU160_SEL = 0;                                  // regs
617
                                                                WE              = 6'b010x00;                    // PC
618
                                                                REG_RSEL        = 4'b111x;                              // tmp7
619
                                                        end
620
                                                endcase
621
//                              -----------------------         JP, OUT (n) A, EX (SP) HL, DI --------------------
622
                                        4'b0011:
623
                                                case(FETCH[5:4])
624
                                                        2'b00:                                  // JP
625
                                                                case(STAGE[1:0])
626
                                                                        2'b00, 2'b01:   begin                           // stage1,2 - read addr
627
                                                                                ALU160_SEL = 1;                                 // pc
628
                                                                                DINW_SEL = 1;                                           // DI
629
                                                                                WE              = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // PC, hi/lo
630
                                                                                next_stage = 1;
631
                                                                                REG_WSEL        = 4'b111x;                              // tmp7
632
                                                                                M1              = 0;
633
                                                                        end
634
                                                                        2'b10: begin                                            // stage3
635
                                                                                ALU160_SEL = 0;                                  // regs
636
                                                                                WE              = 6'b010x00;                    // PC
637
                                                                                REG_RSEL        = 4'b111x;                              // tmp7
638
                                                                        end
639
                                                                endcase
640
                                                        2'b01:                                  // OUT (n), a - stage1 - read n
641
                                                                case(STAGE[1:0])
642
                                                                        2'b00: begin
643
                                                                                ALU160_SEL = 1;                                 // pc
644
                                                                                DINW_SEL = 1;                                           // DI
645
                                                                                WE              = 6'b010x01;                    // PC, lo
646
                                                                                next_stage = 1;
647
                                                                                REG_WSEL        = 4'b011x;                              // tmpLO
648
                                                                                M1              = 0;
649
                                                                        end
650
                                                                        2'b01: begin            // stage2 - OUT
651
                                                                                DO_SEL  = 2'b00;                                        // ALU80
652
                                                                                ALU160_SEL = 0;                                  // regs
653
                                                                                WE              = 6'b000x00;                    // nothing
654
                                                                                next_stage = 1;
655
                                                                                REG_WSEL        = 4'b0110;                              // A
656
                                                                                REG_RSEL        = 4'b011x;                              // A-tmpLO
657
                                                                                M1              = 0;
658
                                                                                MREQ            = 0;
659
                                                                                WR              = 1;
660
                                                                                IORQ            = 1;
661
                                                                        end
662
                                                                        2'b10: begin            // stage3 - fetch
663
                                                                                ALU160_SEL = 1;                 // PC
664
                                                                                WE              = 6'b010x00;    // PC
665
                                                                        end
666
                                                                endcase
667
                                                        2'b10:                          // EX (SP), HL
668
                                                                case(STAGE[2:0])
669
                                                                        3'b000, 3'b001: begin                   // stage1,2 - pop tmp16
670
                                                                                ALU160_SEL = 0;                                  // regs
671
                                                                                DINW_SEL = 1;                                           // DI
672
                                                                                WE              = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};                   // SP, lo/hi
673
                                                                                next_stage = 1;
674
                                                                                REG_WSEL        = 4'b111x;                              // tmp16
675
                                                                                REG_RSEL        = 4'b101x;                              // SP
676
                                                                                M1              = 0;
677
                                                                        end
678
                                                                        3'b010, 3'b011: begin                   // stage3,4 - push hl
679
                                                                                DO_SEL  = 2'b00;                                        // ALU80
680
                                                                                ALU160_SEL = 0;                                  // regs
681
                                                                                WE              = 6'b001x00;                    // SP
682
                                                                                ALU16OP = 5;                                            // dec
683
                                                                                next_stage = 1;
684
                                                                                REG_WSEL        = {3'b010, STAGE[0]};// H/L      
685
                                                                                REG_RSEL        = 4'b101x;                              // SP
686
                                                                                M1              = 0;
687
                                                                                WR                      = 1;
688
                                                                        end
689
                                                                        3'b100, 3'b101: begin           // stage5,6
690
                                                                                ALU160_SEL = 1;                                 // pc
691
                                                                                DINW_SEL = 0;                                            // ALU8OUT
692
                                                                                WE              = {1'b0, STAGE[0], 2'b0x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};      // PC, lo/hi
693
                                                                                ALU8OP  = 29;           // pass D1
694
                                                                                next_stage = !STAGE[0];
695
                                                                                REG_WSEL        = 4'b010x;              // HL
696
                                                                                REG_RSEL        = {3'b111, !STAGE[0]};           // tmp16
697
                                                                                M1              = STAGE[0];
698
                                                                                MREQ            = STAGE[0];
699
                                                                        end
700
                                                                endcase
701
                                                        2'b11:  begin                   // DI
702
                                                                ALU160_SEL = 1;                 // PC
703
                                                                WE              = 6'b010x00;    // PC
704
                                                                status[2:1] = 2'b10;    // set EI flags
705
                                                        end
706
                                                endcase
707
//                              -----------------------         CALL cc --------------------
708
                                        4'b0100, 4'b1100:
709
                                                case(STAGE[2:0])
710
                                                        3'b000, 3'b001:         // stage 1,2 - load addr
711
                                                                if(FlagMux[FETCH[5:3]]) begin
712
                                                                        ALU160_SEL = 1;                                 // pc
713
                                                                        DINW_SEL = 1;                                           // DI
714
                                                                        WE              = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // PC, hi/lo
715
                                                                        next_stage = 1;
716
                                                                        REG_WSEL        = 4'b111x;                              // tmp7
717
                                                                        M1              = 0;
718
                                                                end else begin
719
                                                                        ALU160_SEL = 1;                                 // pc
720
                                                                        WE              = 6'b010x00;                    // PC
721
                                                                        ALU16OP = 2;                                            // add2
722
                                                                end
723
                                                        3'b010, 3'b011: begin           // stage 3,4 - push pc
724
                                                                DO_SEL  = {1'b0, STAGE[0]};      // pc hi/lo
725
                                                                ALU160_SEL = 0;                                  // regs
726
                                                                WE              = 6'b001x00;                    // SP
727
                                                                ALU16OP = 5;                                            // DEC
728
                                                                next_stage = 1;
729
                                                                REG_WSEL        = 4'b1xxx;                              // pc
730
                                                                REG_RSEL        = 4'b101x;                              // sp
731
                                                                M1              = 0;
732
                                                                WR                      = 1;
733
                                                        end
734
                                                        3'b100: begin   // stage5
735
                                                                ALU160_SEL = 0;                                  // regs
736
                                                                WE              = 6'b010x00;                    // PC
737
                                                                REG_RSEL        = 4'b111x;                              // tmp7
738
                                                        end
739
                                                endcase
740
//                              -----------------------         PUSH --------------------
741
                                        4'b0101:
742
                                                case(STAGE[1:0])
743
                                                        2'b00, 2'b01: begin                     // stage1,2
744
                                                                DO_SEL  = {STAGE[0] & op16[2], 1'b0};            // FLAGS/ALU80
745
                                                                ALU160_SEL = 0;                          // regs
746
                                                                WE              = 6'b001x00;            // SP
747
                                                                ALU16OP = 5;                            // dec
748
                                                                next_stage = 1;
749
                                                                REG_WSEL        = {1'b0, FETCH[5:4], STAGE[0]};
750
                                                                REG_RSEL        = 4'b101x;                              // SP
751
                                                                M1              = 0;
752
                                                                WR                      = 1;
753
                                                        end
754
                                                        2'b10: begin                                    //stage3
755
                                                                ALU160_SEL = 1;                         // PC
756
                                                                WE              = 6'b010x00;            // PC
757
                                                        end
758
                                                endcase
759
//                              -----------------------         op A, n  --------------------
760
                                        4'b0110, 4'b1110:
761
                                                if(!STAGE[0]) begin                      // stage1, read n
762
                                                        ALU160_SEL = 1;                                 // pc
763
                                                        DINW_SEL = 1;                                           // DI
764
                                                        WE              = 6'b010x01;                    // PC, lo
765
                                                        next_stage = 1;
766
                                                        REG_WSEL        = 4'b011x;                              // tmpLO
767
                                                        M1              = 0;
768
                                                end else begin                                  // stage 2
769
                                                        DINW_SEL = 0;                                            // ALU8OUT[7:0]
770
                                                        ALU160_SEL = 1;                                 // pc
771
                                                        WE              = {4'b110x, ~&FETCH[5:3], 1'bx};                        // flags, PC, hi
772
                                                        ALU8OP  = {2'b00, FETCH[5:3]};
773
                                                        REG_WSEL        = 4'b0110;                              // A
774
                                                        REG_RSEL        = 4'b0111;                              // tmpLO
775
                                                end
776
//                              -----------------------         RST  --------------------
777
                                        4'b0111, 4'b1111:
778
                                                case(STAGE[1:0])
779
                                                        2'b00, 2'b01: begin             // stage 1,2 - push pc
780
                                                                DO_SEL  = {1'b0, STAGE[0]};      // pc hi/lo
781
                                                                ALU160_SEL = 0;                                  // regs
782
                                                                WE              = 6'b001x00;                    // SP
783
                                                                ALU16OP = 5;                                            // DEC
784
                                                                next_stage = 1;
785
                                                                REG_WSEL        = 4'b1xxx;                              // pc
786
                                                                REG_RSEL        = 4'b101x;                              // sp
787
                                                                M1              = 0;
788
                                                                WR                      = 1;
789
                                                        end
790
                                                        2'b10:  begin                           // stage3
791
                                                                ALU160_SEL = 0;                                  // regs
792
                                                                WE              = 6'b010x00;                    // PC
793
                                                                REG_RSEL        = 4'b110x;                              // const
794
                                                        end
795
                                                endcase
796
//                              -----------------------         RET, EXX, JP (HL), LD SP HL --------------------
797
                                        4'b1001:
798
                                                case(FETCH[5:4])
799
                                                        2'b00:                          // RET
800
                                                                case(STAGE[1:0])
801
                                                                        2'b00, 2'b01:   begin           // stage1, stage2 - pop addr
802
                                                                                ALU160_SEL = 0;                          // regs
803
                                                                                DINW_SEL = 1;                                   // DI
804
                                                                                WE              = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // SP, lo/hi
805
                                                                                next_stage = 1;
806
                                                                                REG_WSEL        = 4'b111x;                      // tmp16
807
                                                                                REG_RSEL        = 4'b101x;                      // SP
808
                                                                                M1              = 0;
809
                                                                        end
810
                                                                        2'b10: begin                    // stage3 - jump
811
                                                                                ALU160_SEL = 0;                                  // regs
812
                                                                                WE              = 6'b010x00;                    // PC
813
                                                                                REG_RSEL        = 4'b111x;                              // tmp16
814
                                                                        end
815
                                                                endcase
816
                                                        2'b01: begin                    // EXX
817
                                                                ALU160_SEL = 1;                 // PC
818
                                                                WE              = 6'b010x00;    // PC
819
                                                        end
820
                                                        2'b10:  begin           // JP (HL)
821
                                                                ALU160_SEL = 0;                                  // regs
822
                                                                WE              = 6'b010x00;                    // PC
823
                                                                REG_RSEL        = 4'b010x;                              // HL
824
                                                        end
825
                                                        2'b11: begin    // LD SP,HL     
826
                                                                if(!STAGE[0]) begin                      // stage1
827
                                                                        ALU160_SEL = 0;                          // regs
828
                                                                        WE              = 6'b001x00;            // SP
829
                                                                        ALU16OP = 4;                                    // NOP, no post inc
830
                                                                        next_stage = 1;
831
                                                                        REG_RSEL        = 4'b010x;                      // HL
832
                                                                        M1              = 0;
833
                                                                        MREQ            = 0;
834
                                                                end else begin                                          // stage2
835
                                                                        ALU160_SEL = 1;                         // pc
836
                                                                        WE              = 6'b010x00;            // PC
837
                                                                end
838
                                                        end
839
                                                endcase
840
//                              -----------------------         CB, IN A (n), EX DE HL, EI --------------------
841
                                        4'b1011:
842
                                                case(FETCH[5:4])
843
                                                        2'b00: begin                            // CB prefix, nop
844
                                                                ALU160_SEL = 1;                 // PC
845
                                                                WE              = 6'b010000;    // PC
846
                                                        end
847
                                                        2'b01:                                  // IN A, (n)
848
                                                                case(STAGE[1:0])
849
                                                                        2'b00: begin            //stage1 - read n
850
                                                                                ALU160_SEL = 1;                         // pc
851
                                                                                DINW_SEL = 1;                                   // DI
852
                                                                                WE              = 6'b010x01;            // PC, lo
853
                                                                                next_stage = 1;
854
                                                                                REG_WSEL        = 4'b011x;                      // tmpLO
855
                                                                                M1              = 0;
856
                                                                        end
857
                                                                        2'b01: begin            // stage2 - IN
858
                                                                                ALU160_SEL = 0;                          // regs
859
                                                                                DINW_SEL = 1;                                   // DI
860
                                                                                WE              = 6'b000x1x;            // hi
861
                                                                                next_stage = 1;
862
                                                                                REG_WSEL        = 4'b011x;                      // A
863
                                                                                REG_RSEL        = 4'b011x;                      // A - tmpLO
864
                                                                                M1              = 0;
865
                                                                                MREQ            = 0;
866
                                                                                IORQ            = 1;
867
                                                                        end
868
                                                                        2'b10: begin            // stage3 - fetch
869
                                                                                ALU160_SEL = 1;                 // PC
870
                                                                                WE              = 6'b010x00;    // PC
871
                                                                        end
872
                                                                endcase
873
                                                        2'b10: begin                    // EX DE, HL
874
                                                                ALU160_SEL = 1;                 // PC
875
                                                                WE              = 6'b010x00;    // PC
876
                                                                status[0] = 1;
877
                                                        end
878
                                                        2'b11: begin                    // EI
879
                                                                ALU160_SEL = 1;                 // PC
880
                                                                WE              = 6'b010x00;    // PC
881
                                                                status[2:1] = 2'b11;
882
                                                        end
883
                                                endcase
884
//                              -----------------------         CALL , DD, ED, FD --------------------
885
                                        4'b1101:
886
                                                case(FETCH[5:4])
887
                                                        2'b00:                                  // CALL
888
                                                                case(STAGE[2:0])
889
                                                                        3'b000, 3'b001: begin                           // stage 1,2 - load addr
890
                                                                                ALU160_SEL = 1;                                 // pc
891
                                                                                DINW_SEL = 1;                                   // DI
892
                                                                                WE              = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]};           // PC, hi/lo
893
                                                                                next_stage = 1;
894
                                                                                REG_WSEL        = 4'b111x;                      // tmp7
895
                                                                                M1              = 0;
896
                                                                        end
897
                                                                        3'b010, 3'b011: begin           // stage 3,4 - push pc
898
                                                                                DO_SEL  = {1'b0, STAGE[0]};      // pc hi/lo
899
                                                                                ALU160_SEL = 0;                                  // regs
900
                                                                                WE              = 6'b001x00;                    // SP
901
                                                                                ALU16OP = 5;                                    // DEC
902
                                                                                next_stage = 1;
903
                                                                                REG_WSEL        = 4'b1xxx;                      // pc
904
                                                                                REG_RSEL        = 4'b101x;                      // sp
905
                                                                                M1              = 0;
906
                                                                                WR                      = 1;
907
                                                                        end
908
                                                                        3'b100: begin   // stage5 - jump
909
                                                                                ALU160_SEL = 0;                                  // regs
910
                                                                                WE              = 6'b010x00;                    // PC
911
                                                                                REG_RSEL        = 4'b111x;                      // tmp7
912
                                                                        end
913
                                                                endcase
914 17 ndumitrach
                                                        2'b01: begin    // DD - indexed mode
915 14 ndumitrach
                                                                ALU160_SEL = 1;                         // PC
916 17 ndumitrach
                                                                if(!STAGE[0]) begin
917
                                                                        WE              = 6'b010100;    // PC, tmpHI
918
                                                                        next_stage = 1;
919
                                                                        M1              = 0;
920
                                                                end else begin
921
                                                                        WE = 6'b010000;         // PC
922
                                                                        status[3] = 1'b1;       // set indexed mode
923
                                                                end
924
                                                        end
925
                                                        2'b10, 2'b11: begin             // ED, FD - IY
926
                                                                ALU160_SEL = 1;                         // PC
927 14 ndumitrach
                                                                WE              = 6'b010x00;            // PC
928
                                                        end
929
                                                endcase
930
                                endcase
931
 
932
//------------------------------------------- // RST, INT ----------------------------------------------------
933
                        3'b110: begin                   // RESET: DI, pC <- 0
934
                                ALU160_SEL = 0;                                  // regs
935
                                WE              = 6'bx1xx00;                    // PC
936
                                ALU16OP = 4;                                    // NOP
937
                                REG_RSEL        = 4'b110x;                      // const
938
                                M1              = 0;
939
                                MREQ            = 0;
940
                                status[2:1] = 2'b10;                    // DI
941
                        end
942
                        3'b100: begin                           // INT
943
                                ALU160_SEL = 1;                                 // pc
944
                                WE              = 6'b010x00;                    // PC
945
                                ALU16OP = FETCH[1] ? 4 : 5;             // NOP(HALT)/DEC(else)
946
                                MREQ            = 0;
947
                                IORQ            = 1;
948
                                status[2:1]     = 2'b10;                        // DI
949
                        end
950
                endcase
951
        end
952
 
953
endmodule
954
 
955
//FLAGS: S Z X1 N X2 PV N C
956
//      OP[4:0]
957
//      00000   -       ADD     D0,D1
958
//      00001   -       ADC     D0,D1
959
//      00010   -       SUB     D0,D1
960
//      00011   -       SBC     D0,D1
961
//      00100   -       AND     D0,D1
962
//      00101   -       XOR     D0,D1
963
//      00110   -       OR              D0,D1
964
//      00111   -       CP              D0,D1
965
//      01000   -       INC     D0
966
//      01001   -       CPL     D0
967
// 01010        -       DEC     D0
968
//      01101   -       DAA=CPL
969
//      01110   -       INC16
970
//      01111   -  DEC16
971
// 10000        -       ADD16LO
972
//      10001   -       ADD16HI
973
//      10010   -       
974
//      10011   -       
975
//      10100   -       CCF, pass D0
976
// 10101        -       SCF, pass D0
977
// 10110        -       
978
//      10111   -       
979
//      11000   -       RLCA    D0
980
//      11001   -       RRCA    D0
981
//      11010   -       RLA     D0
982
//      11011   -       RRA     D0
983
//      11101   -       IN, pass D1
984
//      11110   -       FLAGS <- D0
985
///////////////////////////////////////////////////////////////////////////////////
986 18 ndumitrach
module N8080_ALU8(
987 14 ndumitrach
    input [7:0]D0,
988
    input [7:0]D1,
989
         input [7:0]FIN,
990
    input [4:0]OP,
991
 
992
    output reg[7:0]FOUT,
993
    output reg [15:0]ALU8DOUT
994
    );
995
 
996
        wire parity = ~^ALU8DOUT[15:8];
997
        wire zero = ~|ALU8DOUT[15:8];
998
        reg cin;
999
        reg [7:0]_d1mux;
1000
        wire [7:0]d1mux = OP[1] ? ~_d1mux : _d1mux;
1001
        wire [8:0]sum = D0 + d1mux + cin;
1002
        wire overflow = (D0[7] & d1mux[7] & !sum[7]) | (!D0[7] & !d1mux[7] & sum[7]);
1003
        wire [7:0]log;
1004
        reg [3:0]logop;
1005
        wire csin = OP[1] ? FIN[0] : OP[0] ? D0[0] : D0[7];
1006
        wire [7:0]shift = OP[0] ? {csin, D0[7:1]} : {D0[6:0], csin};
1007
        wire [15:0]inc16 = OP[0] ? {D0, D1} - 1'b1 : {D0, D1} + 1'b1;
1008
 
1009 18 ndumitrach
        N8080_LOG8 log8_unit
1010 14 ndumitrach
        (
1011
                .A(D0),
1012
                .B(D1),
1013
                .O(log),
1014
                .op(logop)
1015
        );
1016
 
1017
        always @* begin
1018
                ALU8DOUT = {sum[7:0], sum[7:0]};
1019
                logop = 4'bxxxx;
1020
                case({OP[4:2]})
1021
                        0,1,4,7: _d1mux = D1;
1022
                        default: _d1mux = 8'h01;
1023
                endcase
1024
                case({OP[2:0], FIN[0]})
1025
                        0,1,2,7,8,9,10,11,12,13: cin = 0;
1026
                        3,4,5,6,14,15: cin = 1;
1027
                endcase
1028
 
1029
                FOUT = {FIN[7:6], 3'b000, FIN[2], 1'b0, FIN[0]};
1030
                case(OP[4:0])
1031
                        0,1,2,3,8,10:    begin           // ADD, ADC, SUB, SBC, INC, DEC
1032
                                FOUT[0] = OP[3] ? FIN[0] : (sum[8] ^ OP[1]); // inc/dec
1033
                                FOUT[2] = overflow;
1034
                                FOUT[6] = zero;
1035
                                FOUT[7] = ALU8DOUT[15];
1036
                        end
1037
                        16,17:  begin           // ADD16LO, ADD16HI
1038
                                FOUT[0] = sum[8];
1039
                        end
1040
                        7: begin                // CP
1041
                                FOUT[0] = !sum[8];
1042
                                FOUT[2] = overflow;
1043
                                FOUT[6] = zero;
1044
                                FOUT[7] = ALU8DOUT[15];
1045
                        end
1046
                        4,5,6: begin            //AND, XOR, OR
1047
                                ALU8DOUT = {log, log};
1048
                                logop = OP[0] ? 4'b0110 : OP[1] ? 4'b1110 : 4'b1000;
1049
                                FOUT[0] = 0;
1050
                                FOUT[2] = parity;
1051
                                FOUT[6] = zero;
1052
                                FOUT[7] = ALU8DOUT[15];
1053
                        end
1054
                        9,13: begin                     // CPL
1055
                                ALU8DOUT = {log, log};
1056
                                logop = 4'b0011; // ~D0
1057
                                FOUT[0] = FIN[0];
1058
                        end
1059
                        14,15: begin    // inc/dec 16
1060
                                ALU8DOUT = inc16;
1061
                                FOUT[2] = ALU8DOUT != 0;
1062
                        end
1063
                        20,21: begin            // CCF, SCF
1064
                                ALU8DOUT = {log, log};
1065
                                logop = 4'b1100; // D0
1066
                                FOUT[0] = OP[0] ? 1'b1 : !FIN[0];
1067
                        end
1068
                        24,25,26,27: begin                                                      // ROT
1069
                                ALU8DOUT[15:8] = {shift, shift};
1070
                                FOUT[0] = OP[0] ? D0[0] : D0[7];
1071
                        end
1072
                        29:     begin           // IN, pass D1
1073
                                ALU8DOUT = {log, log};
1074
                                logop = 4'b1010; // D1
1075
                                FOUT[2] = parity;
1076
                                FOUT[6] = zero;
1077
                                FOUT[7] = ALU8DOUT[15];
1078
                        end
1079
                        30: {FOUT[7:6], FOUT[2], FOUT[0]} = {D0[7:6], D0[2], D0[0]};              // FLAGS <- D0
1080
                        default:;
1081
                endcase
1082
        end
1083
endmodule
1084
 
1085 18 ndumitrach
module N8080_LOG8(
1086 14 ndumitrach
        input [7:0]A,
1087
        input [7:0]B,
1088
        input [3:0]op, // 0=0, 1=~(A|B), 2=~A&B, 3=~A, 4=A&~B, 5=~B, 6=A^B, 7=~(A&B), 8=A&B, 9=~(A^B), 10=B, 11=~A|B, 12=A, 13=A|~B, 14=A|B, 15=-1
1089
 
1090
        output [7:0]O
1091
        );
1092
 
1093
        assign O[0] = op[{A[0], B[0]}];
1094
        assign O[1] = op[{A[1], B[1]}];
1095
        assign O[2] = op[{A[2], B[2]}];
1096
        assign O[3] = op[{A[3], B[3]}];
1097
        assign O[4] = op[{A[4], B[4]}];
1098
        assign O[5] = op[{A[5], B[5]}];
1099
        assign O[6] = op[{A[6], B[6]}];
1100
        assign O[7] = op[{A[7], B[7]}];
1101
endmodule
1102
 
1103 18 ndumitrach
module N8080_ALU16(
1104 14 ndumitrach
    input [15:0]D0,
1105
    input [7:0]D1,
1106
    input [2:0]OP,       // 0-NOP, 1-INC, 2-INC2, 3-ADD, 4-NOP, 5-DEC, 6-DEC2
1107
 
1108
    output wire[15:0] DOUT
1109
    );
1110
 
1111
        reg [7:0] mux;
1112
        always @*
1113
                case(OP)
1114
                        0: mux = 8'd0;                   // post inc
1115
                        1: mux = 8'd1;                  // post inc
1116
                        2: mux = 8'd2;                  // post inc
1117
                        3: mux = D1;                    // post inc
1118
                        4: mux = 8'd0;                  // no post inc                  
1119
                        5: mux = -8'd1;         // no post inc
1120
                        6: mux = -8'd2;         // no post inc
1121
                        7: mux = 8'dx;
1122
                endcase
1123
 
1124
        assign DOUT = D0 + {{8{mux[7]}}, mux};
1125
endmodule
1126
 
1127 18 ndumitrach
module N8080_Reg(
1128 14 ndumitrach
        input rstatus,                  // hl-de
1129
        input M1,
1130
        input [5:0]WE,                   // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
1131
        input CLK,
1132
        input [15:0]ALU8OUT,     // CPU data out bus (output of alu8)
1133
        input [7:0]DI,                   // CPU data in bus
1134
        input [15:0]ADDR,                // CPU addr bus
1135
        input [7:0]CONST,
1136
        input [7:0]ALU8FLAGS,
1137
        input [1:0]DO_SEL,               // select DO betwen ALU8OUT lo and th register
1138
        input ALU160_sel,               // 0=REG_RSEL, 1=PC
1139
        input [3:0]REG_WSEL,     // rdow:        [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-x  ----- [0] = 0HI,1LO
1140
        input [3:0]REG_RSEL,     // mux_rdor:   [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-R, 5=SP, 7=tmp   ----- [0] = 0HI, 1LO
1141
        input DINW_SEL,         // select RAM write data between (0)ALU8OUT, and 1(DI)
1142
        input [2:0]ALU16OP,      // ALU16OP
1143
        input WAIT,                             // wait
1144
 
1145
        output reg [7:0]DO,                      // CPU data out bus
1146
        output reg [7:0]ALU80,
1147
        output reg [7:0]ALU81,
1148
        output reg [15:0]ALU160,
1149
        output [7:0]ALU161,
1150
        output [7:0]FLAGS
1151
        );
1152
 
1153
// latch registers
1154
        reg [15:0]pc=0;                           // program counter
1155
        reg [15:0]sp;                            // stack pointer
1156
        reg [7:0]flg = 0;
1157
        reg [7:0]th;                             // temp high
1158
 
1159
// internal wires       
1160
        wire [15:0]rdor; // R out from RAM
1161
        wire [15:0]rdow; // W out from RAM
1162
        wire [2:0]SELW;          // RAM W port sel
1163
        wire [2:0]SELR;          // RAM R port sel
1164
        reg  [15:0]DIN;          // RAM W in data
1165
        reg [15:0]mux_rdor;      // (3)A reversed mixed with TL, (4)I mixed with R (5)SP
1166
 
1167
//------------------------------------ RAM block registers ----------------------------------
1168
// 0:BC, 1:DE, 2:HL, 3:A-x, 4:BC', 5:DE', 6:HL', 7:A'-x, 8:tmp
1169 18 ndumitrach
   N8080_RAM16X8D_regs regs_lo (
1170 14 ndumitrach
      .DPO(rdor[7:0]),   // Read-only data output
1171
      .SPO(rdow[7:0]),   // R/W data output
1172
      .A(SELW),          // R/W address
1173
      .D(DIN[7:0]),      // Write data input
1174
      .DPRA(SELR),               // Read-only address
1175
      .WCLK(CLK),        // Write clock input
1176
      .WE(WE[0] & !WAIT) // Write enable input
1177
   );
1178
 
1179 18 ndumitrach
   N8080_RAM16X8D_regs regs_hi (
1180 14 ndumitrach
      .DPO(rdor[15:8]),  // Read-only data output
1181
      .SPO(rdow[15:8]),  // R/W data output
1182
      .A(SELW),          // R/W address
1183
      .D(DIN[15:8]),     // Write data input
1184
      .DPRA(SELR),               // Read-only address
1185
      .WCLK(CLK),        // Write clock input
1186
      .WE(WE[1] & !WAIT) // Write enable input
1187
   );
1188
 
1189
        wire [15:0]ADDR1 = ADDR + !ALU16OP[2]; // address post increment
1190
        always @(posedge CLK)
1191
                if(!WAIT) begin
1192
                        if(WE[2]) th <= DI;
1193
                        if(WE[3]) sp <= ADDR1;
1194
                        if(WE[4]) pc <= ADDR1;
1195
                        if(WE[5]) flg <= ALU8FLAGS;
1196
                end
1197
 
1198
        assign ALU161 = th;
1199
        assign FLAGS = flg;
1200
 
1201
        always @* begin
1202
                DIN = DINW_SEL ? {DI, DI} : ALU8OUT;
1203
                ALU80 = REG_WSEL[0] ? rdow[7:0] : rdow[15:8];
1204
                ALU81 = REG_RSEL[0] ? mux_rdor[7:0] : mux_rdor[15:8];
1205
                ALU160 = ALU160_sel ? pc : mux_rdor;
1206
 
1207
                case({REG_WSEL[3], DO_SEL})
1208
                        0:       DO = ALU80;
1209
                        1:      DO = th;
1210
                        2:      DO = FLAGS;
1211
                        3:      DO = ALU8OUT[7:0];
1212
                        4:      DO = pc[15:8];
1213
                        5:      DO = pc[7:0];
1214
                        6:      DO = sp[15:8];
1215
                        7:      DO = sp[7:0];
1216
                endcase
1217
                case({ALU16OP == 4, REG_RSEL[3:0]})
1218
                        5'b01010, 5'b01011: mux_rdor = sp;
1219
                        5'b01100, 5'b01101, 5'b11100, 5'b11101: mux_rdor = {8'b0, CONST};
1220
                        default: mux_rdor = rdor;
1221
                endcase
1222
        end
1223
 
1224 18 ndumitrach
        N8080_RegSelect WSelectW(.SEL(REG_WSEL[3:1]), .RAMSEL(SELW), .rstatus(rstatus));
1225
        N8080_RegSelect WSelectR(.SEL(REG_RSEL[3:1]), .RAMSEL(SELR), .rstatus(rstatus));
1226 14 ndumitrach
 
1227
endmodule
1228
 
1229
 
1230 18 ndumitrach
module N8080_RegSelect(
1231 14 ndumitrach
        input [2:0]SEL,
1232
        input rstatus,                  // 2=hl-de
1233
 
1234
        output reg [2:0]RAMSEL
1235
        );
1236
 
1237
        always @* begin
1238
                case(SEL)
1239
                        0: RAMSEL = 3'b000;      // BC
1240
                        1: RAMSEL = rstatus ? 3'b010 : 3'b001;  // HL - DE
1241
                        2: RAMSEL = rstatus ? 3'b001 : 3'b010;  // DE - HL
1242 17 ndumitrach
                        3: RAMSEL = 3'b011;                                     // A-TL
1243
                        default: RAMSEL = 3'b100;       // I-R, tmp SP, zero, temp
1244 14 ndumitrach
                endcase
1245
        end
1246
endmodule
1247
 
1248 18 ndumitrach
module N8080_RAM16X8D_regs(
1249 14 ndumitrach
      input [2:0]A,              // R/W address 
1250
      input [7:0]D,        // Write data input
1251
      input [2:0]DPRA,           // Read-only address
1252
      input WCLK,                       // Write clock
1253
      input WE,                 // Write enable
1254
 
1255
      output [7:0]DPO,     // Read-only data output
1256
      output [7:0]SPO     // R/W data output
1257
   );
1258
 
1259
        reg [7:0]data[4:0];
1260
        assign DPO = data[DPRA];
1261
        assign SPO = data[A];
1262
 
1263
        always @(posedge WCLK)
1264
                if(WE) data[A] <= D;
1265
 
1266
endmodule
1267
 

powered by: WebSVN 2.1.0

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