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

Subversion Repositories nextz80

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

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

powered by: WebSVN 2.1.0

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