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

Subversion Repositories cpu8080

[/] [cpu8080/] [trunk/] [project/] [cpu8080.v] - Blame information for rev 18

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 samiam9512
`timescale 1ns / 1ps
2
////////////////////////////////////////////////////////////////////////////////
3
// Company:                                                                   //  
4
// Engineer:       Scott Moore                                                //
5
//                                                                            //
6
// Create Date:    11:45:32 09/04/2006                                        // 
7
// Design Name:                                                               // 
8
// Module Name:    cpu8080                                                    //
9
// Project Name:   cpu8080                                                    //
10
// Target Devices: xc3c200, xc3s1000                                          //
11
// Tool versions:                                                             //
12
// Description:                                                               //
13
//                                                                            //
14
//     Executes the 8080 instruction set. It is designed to be an internal    //
15
//     cell. Each of the I/Os are positive logic, and all signals are         //
16
//     constant with the exception of the data bus. The control signals are   //
17
//     fully decoded (unlike the orignal 8080), and features read and write   //
18
//     signals for both memory and I/O space. The I/O space is an 8 bit       //
19 9 samiam9512
//     address as in the original 8080. It does NOT echo the lower 8 bits to  //
20
//     the higher 8 bits, as was the practice in some systems.                //
21 2 samiam9512
//                                                                            //
22
//     Like the original 8080, the interrupt vectoring is fully external. The //
23
//     the external controller forces a full instruction onto the data bus.   //
24
//     The sequence begins with the assertion of interrupt request. The CPU   //
25
//     will then assert interrupt acknowledge, then it will run a special     //
26 9 samiam9512
//     read cycle with inta asserted for each cycle of a possibly             //
27 2 samiam9512
//     multibyte instruction. This matches the original 8080, which typically //
28
//     used single byte restart instructions to form a simple interrupt       //
29
//     controller, but was capable of full vectoring via insertion of a jump, //
30
//     call or similar instruction.                                           //
31 18 samiam9512
//                                                                            //
32 9 samiam9512
//     Note that the interrupt vector instruction should branch. This is      //
33
//     because the PC gets changed by the vector instruction, so if it does   //
34
//     not branch, it will have skipped a number of bytes after the interrupt //
35
//     equivalent to the vector instruction. The only instructions that       //
36
//     should really be used to vector are jmp, rst and call instructions.    //
37
//     Specifically, rst and call instruction compensate for the pc movement  //
38
//     by putting the pc unmodified on the stack.                             //
39 2 samiam9512
//                                                                            //
40
//     The memory, I/O and interrupt fetches all obey a simple clocking       //
41
//     sequence as follows. The CPU uses the positive clock edge to assert    //
42
//     and sample signals and data. The external logic theoretically uses the //
43 9 samiam9512
//     negative edge to check signal assertions and sample data, but it can   //
44 2 samiam9512
//     either use the negative edge, or actually be asynronous logic.         //
45
//                                                                            //
46
//     A standard read sequence is as follows:                                //
47
//                                                                            //
48
//     1. At the positive clock edge, readmem, readio or readint is asserted. //
49 7 samiam9512
//     2. At the negative clock edge (or immediately), the external memory    //
50 2 samiam9512
//        places data onto the data bus.                                      //
51 18 samiam9512
//     3. We hold automatically for one cycle.                                //
52
//     4. At the next positive clock edge, the data is sampled, and the read  //
53 2 samiam9512
//        Signal is deasserted.                                               //
54
//                                                                            //
55
//     A standard write sequence is as follows:                               //
56
//                                                                            //
57
//     1. At the positive edge, data is asserted on the data bus.             //
58 9 samiam9512
//     2. At the next postive clock edge, writemem or writeio is asserted.    //
59 2 samiam9512
//     3. At the next positive clock edge, writemem or writeio is deasserted. //
60 9 samiam9512
//     4. At the next positive edge, the data is deasserted.                  //
61 2 samiam9512
//                                                                            //
62
// Dependencies:                                                              //
63
//                                                                            //
64
// Revision:                                                                  //
65
// Revision 0.01 - File Created                                               //
66
// Additional Comments:                                                       //
67
//                                                                            //
68
////////////////////////////////////////////////////////////////////////////////
69
 
70
//
71
// CPU states
72
//
73
 
74 18 samiam9512
`define cpus_idle     6'h00 // Idle
75
`define cpus_fetchi   6'h01 // Instruction fetch
76
`define cpus_fetchi2  6'h02 // Instruction fetch 2
77
`define cpus_fetchi3  6'h03 // Instruction fetch 3
78
`define cpus_fetchi4  6'h04 // Instruction fetch 4
79
`define cpus_halt     6'h05 // Halt (wait for interrupt)
80
`define cpus_alucb    6'h06 // alu cycleback
81
`define cpus_indcb    6'h07 // inr/dcr cycleback
82
`define cpus_movmtbc  6'h08 // Move memory to bc
83
`define cpus_movmtde  6'h09 // Move memory to de
84
`define cpus_movmthl  6'h0a // Move memory to hl
85
`define cpus_movmtsp  6'h0b // Move memory to sp
86
`define cpus_lhld     6'h0c // LHLD
87
`define cpus_jmp      6'h0d // JMP
88
`define cpus_write    6'h0e // write byte
89
`define cpus_write2   6'h0f // write byte #2
90
`define cpus_write3   6'h10 // write byte #3
91
`define cpus_write4   6'h11 // write byte #4
92
`define cpus_read     6'h12 // read byte
93
`define cpus_read2    6'h13 // read byte #2
94
`define cpus_read3    6'h14 // read byte #3
95
`define cpus_pop      6'h15 // POP completion
96
`define cpus_in       6'h16 // IN
97
`define cpus_in2      6'h17 // IN #2
98
`define cpus_in3      6'h18 // IN #3
99
`define cpus_out      6'h19 // OUT
100
`define cpus_out2     6'h1a // OUT #2
101
`define cpus_out3     6'h1b // OUT #3
102
`define cpus_out4     6'h1c // OUT #4
103
`define cpus_movtr    6'h1d // move to register
104
`define cpus_movrtw   6'h1e // move read to write
105
`define cpus_movrtwa  6'h1f // move read to write address
106
`define cpus_movrtra  6'h20 // move read to read address
107
`define cpus_accimm   6'h21 // accumulator immediate operations
108
`define cpus_daa      6'h22 // DAA completion
109 2 samiam9512
 
110
//
111
// Register numbers
112
//
113
 
114
`define reg_b 3'b000 // B
115
`define reg_c 3'b001 // C
116
`define reg_d 3'b010 // D
117
`define reg_e 3'b011 // E
118
`define reg_h 3'b100 // H
119
`define reg_l 3'b101 // L
120
`define reg_m 3'b110 // M
121
`define reg_a 3'b111 // A
122
 
123
//
124
// ALU operations
125
//
126
 
127
`define aluop_add 3'b000 // add
128
`define aluop_adc 3'b001 // add with carry in
129
`define aluop_sub 3'b010 // subtract
130
`define aluop_sbb 3'b011 // subtract with borrow in
131
`define aluop_and 3'b100 // and
132
`define aluop_xor 3'b101 // xor
133
`define aluop_or  3'b110 // or
134
`define aluop_cmp 3'b111 // compare
135
 
136
//
137
// State macros
138
//
139
`define mac_writebyte  1  // write a byte
140
`define mac_readbtoreg 2  // read a byte, place in register
141
`define mac_readdtobc  4  // read double byte to BC
142
`define mac_readdtode  6  // read double byte to DE
143
`define mac_readdtohl  8 // read double byte to HL
144
`define mac_readdtosp  10 // read double byte to SP
145
`define mac_readbmtw   12 // read byte and move to write
146
`define mac_readbmtr   14 // read byte and move to register
147
`define mac_sta        16 // STA
148
`define mac_lda        20 // LDA
149
`define mac_shld       25 // SHLD
150
`define mac_lhld       30 // LHLD
151
`define mac_writedbyte 36 // write double byte
152
`define mac_pop        38 // POP
153
`define mac_xthl       40 // XTHL
154
`define mac_accimm     44 // accumulator immediate
155
`define mac_jmp        45 // JMP
156
`define mac_call       47 // CALL
157
`define mac_in         51 // IN
158
`define mac_out        52 // OUT
159
`define mac_rst        53 // RST
160
 
161
module cpu8080(addr,     // Address out
162
               data,     // Data bus
163
               readmem,  // Memory read   
164
               writemem, // Memory write
165
               readio,   // Read I/O space
166
               writeio,  // Write I/O space
167
               intr,     // Interrupt request 
168
               inta,     // Interrupt request 
169
               waitr,    // Wait request
170
               reset,    // Reset
171
               clock);   // System clock
172
 
173
   output [15:0] addr;
174
   inout  [7:0] data;
175
   output readmem;
176
   output writemem;
177
   output readio;
178
   output writeio;
179
   input  intr;
180
   output inta;
181
   input  waitr;
182
   input  reset;
183
   input  clock;
184
 
185
   // Output or input lines that need to be registered
186
 
187
   reg           readmem;
188
   reg           writemem;
189
   reg    [15:0] pc;
190
   reg    [15:0] addr;
191
   reg           readio;
192
   reg           writeio;
193
   reg           inta;
194
   reg    [15:0] sp;
195
 
196
   // Local registers
197
 
198 18 samiam9512
   reg    [5:0]  state;       // CPU state machine
199 2 samiam9512
   reg    [2:0]  regd;        // Destination register
200
   reg    [7:0]  datao;       // Data output register
201
   reg           dataeno;     // Enable output data
202
   reg    [15:0] waddrhold;   // address holding for write
203
   reg    [15:0] raddrhold;   // address holding for read
204
   reg    [7:0]  wdatahold;   // single byte write data holding
205
   reg    [7:0]  wdatahold2;  // single byte write data holding
206
   reg    [7:0]  rdatahold;   // single byte read data holding
207
   reg    [7:0]  rdatahold2;  // single byte read data holding
208
   reg    [1:0]  popdes;      // POP destination code
209
   reg    [5:0]  statesel;    // state map selector
210 18 samiam9512
   reg    [5:0]  nextstate;   // next state output
211 9 samiam9512
   reg           eienb;       // interrupt enable delay shift reg
212 11 samiam9512
   reg    [7:0]  opcode;      // opcode holding
213 2 samiam9512
 
214
   // Register file. Note that 3'b110 (6) is not used, and is the code for a
215
   // memory reference.
216
 
217
   reg    [7:0]  regfil[0:7];
218
 
219
   // The flags are represented individually
220
 
221
   reg           carry; // carry bit
222
   reg           auxcar; // auxiliary carry bit
223
   reg           sign; // sign bit
224
   reg           zero; // zero bit
225
   reg           parity; // parity bit
226
   reg           ei; // interrupt enable
227 9 samiam9512
   reg           intcyc; // in interrupt cycle
228 2 samiam9512
 
229
   // ALU communication
230
 
231
   wire   [7:0]  alures;  // result
232
   reg    [7:0]  aluopra; // left side operand
233
   reg    [7:0]  aluoprb; // right side operand
234
   reg           alucin;  // carry in
235
   wire          alucout; // carry out
236
   wire          alupar;  // parity out
237
   wire          aluaxc;  // auxiliary carry
238
   reg    [2:0]  alusel;  // alu operational select
239
 
240
   // Instantiate the ALU
241
 
242
   alu alu(alures, aluopra, aluoprb, alucin, alucout, aluzout, alusout, alupar,
243
           aluaxc, alusel);
244
 
245
   always @(posedge clock)
246
      if (reset) begin // syncronous reset actions
247
 
248
      state <= `cpus_fetchi; // Clear CPU state to initial fetch
249
      pc <= 0; // reset program counter to 1st location
250
      dataeno <= 0; // get off the data bus
251
      readmem <= 0; // all signals out false
252
      writemem <= 0;
253
      readio <= 0;
254
      writeio <= 0;
255
      inta <= 0;
256 9 samiam9512
      intcyc <= 0;
257
      ei <= 1;
258
      eienb <= 0;
259 2 samiam9512
 
260
   end else case (state)
261
 
262
      `cpus_fetchi: begin // start of instruction fetch
263
 
264 9 samiam9512
         // if interrupt request is on, enter interrupt cycle, else exit it now
265
         if (intr&&ei) begin
266
 
267
            intcyc <= 1; // enter interrupt cycle
268
            inta <= 1; // activate interrupt acknowledge
269
            ei <= 0; // disable interrupts
270
 
271
         end else begin
272
 
273
            intcyc <= 0; // leave interrupt cycle
274
            readmem <= 1; // activate instruction memory read
275
 
276
         end
277
 
278 2 samiam9512
         addr <= pc; // place current program count on output
279 9 samiam9512
         if (eienb) ei <=1; // process delayed interrupt enable
280
         eienb <=0; // reset interrupt enabler
281 2 samiam9512
         state <= `cpus_fetchi2; // next state
282
 
283
      end
284 11 samiam9512
 
285 18 samiam9512
      `cpus_fetchi2: begin // wait
286 11 samiam9512
 
287
         state <= `cpus_fetchi3; // next state
288 18 samiam9512
 
289
       end
290
 
291
      `cpus_fetchi3: begin // complete instruction memory read
292
 
293
         if (!waitr) begin // no wait selected, otherwise cycle
294
 
295
            opcode <= data; // latch opcode
296
            readmem <= 0; // Deactivate instruction memory read
297
            inta <= 0; // and interrupt acknowledge
298
            state <= `cpus_fetchi4; // next state
299
 
300
         end
301 11 samiam9512
 
302
      end
303
 
304 18 samiam9512
      `cpus_fetchi4: begin // complete instruction memory read
305 2 samiam9512
 
306
         // We split off the instructions into 4 groups. Most of the 8080
307
         // instructions are in the MOV and ACC operations class.
308
 
309 11 samiam9512
         case (opcode[7:6]) // Decode top level
310 2 samiam9512
 
311
            2'b00: begin // 00: Data transfers and others
312
 
313 11 samiam9512
               case (opcode[5:0]) // decode these instructions
314 2 samiam9512
 
315
                  6'b000000: begin // NOP
316
 
317
                     // yes, do nothing
318
 
319
                     state <= `cpus_fetchi; // Fetch next instruction
320
                     pc <= pc+1; // Next instruction byte
321
 
322
                  end
323
 
324
                  6'b110111: begin // STC
325
 
326
                     carry <= 1; // set carry flag
327
                     state <= `cpus_fetchi; // Fetch next instruction
328
                     pc <= pc+1; // Next instruction byte
329
 
330
                  end
331
 
332
                  6'b111111: begin // CMC
333
 
334
                     carry <= ~carry; // complement carry flag
335
                     state <= `cpus_fetchi; // Fetch next instruction
336
                     pc <= pc+1; // Next instruction byte
337
 
338
                  end
339
 
340
                  6'b101111: begin // CMA
341
 
342
                     regfil[`reg_a] <= ~regfil[`reg_a]; // complement accumulator
343
                     state <= `cpus_fetchi; // Fetch next instruction
344
                     pc <= pc+1; // Next instruction byte
345
 
346
                  end
347
 
348
                  6'b100111: begin // DAA
349
 
350
                     // decimal adjust accumulator, or remove by carry any 
351
                     // results in nybbles greater than 9
352
 
353
                     if (regfil[`reg_a][3:0] > 9 || auxcar) begin
354
 
355
                        { carry, regfil[`reg_a] } <= regfil[`reg_a]+6;
356
                        auxcar <= (regfil[`reg_a][3:0]+6 >> 4) & 1;
357
 
358
                     end
359
                     state <= `cpus_daa; // finish DAA
360
                     pc <= pc+1; // Next instruction byte
361
 
362
                  end
363
 
364
                  6'b000100, 6'b001100, 6'b010100, 6'b011100, 6'b100100,
365
                  6'b101100, 6'b110100, 6'b111100, 6'b000101, 6'b001101,
366
                  6'b010101, 6'b011101, 6'b100101, 6'b101101, 6'b110101,
367
                  6'b111101: begin // INR/DCR
368
 
369 11 samiam9512
                     regd <= opcode[5:3]; // get source/destination reg
370
                     aluopra <= regfil[opcode[5:3]]; // load as alu a
371 2 samiam9512
                     aluoprb <= 1; // load 1 as alu b
372 11 samiam9512
                     if (opcode[0]) alusel <= `aluop_sub; // set subtract
373 2 samiam9512
                     else alusel <= `aluop_add; // set add
374
                     state <= `cpus_indcb; // go inr/dcr cycleback
375
                     pc <= pc+1; // Next instruction byte
376
 
377
                  end
378
 
379
                  6'b000010, 6'b010010: begin // STAX
380
 
381
                     wdatahold <= regfil[`reg_a]; // place A as source
382 11 samiam9512
                     if (opcode[4]) // use DE pair
383 2 samiam9512
                        waddrhold <= regfil[`reg_d]<<8|regfil[`reg_d];
384
                     else // use BC pair
385
                        waddrhold <= regfil[`reg_b] << 8|regfil[`reg_c];
386
                     statesel <= `mac_writebyte; // write byte
387
                     state <= `cpus_write;
388
                     pc <= pc+1; // Next instruction byte
389
 
390
                  end
391
 
392
                  6'b001010, 6'b011010: begin // LDAX
393
 
394
                     regd <= `reg_a; // set A as destination
395 11 samiam9512
                     if (opcode[4]) // use DE pair
396 2 samiam9512
                        raddrhold <= regfil[`reg_d]<<8|regfil[`reg_d];
397
                     else // use BC pair
398
                        raddrhold <= regfil[`reg_b]<<8|regfil[`reg_c];
399
                     statesel <= `mac_readbtoreg; // read byte to register
400
                     state <= `cpus_read;
401
                     pc <= pc+1; // Next instruction byte
402
 
403
                  end
404
 
405
                  6'b000111: begin // RLC
406
 
407
                     // rotate left circular
408
                     { carry, regfil[`reg_a] } <=
409
                        (regfil[`reg_a] << 1)+regfil[`reg_a][7];
410
                     state <= `cpus_fetchi; // Fetch next instruction
411
                     pc <= pc+1; // Next instruction byte
412
 
413
                  end
414
 
415
                  6'b010111: begin // RAL
416
 
417
                     // rotate left through carry
418
                     { carry, regfil[`reg_a] } <= (regfil[`reg_a] << 1)+carry;
419
                     state <= `cpus_fetchi; // Fetch next instruction
420
                     pc <= pc+1; // Next instruction byte
421
 
422
                  end
423
 
424
                  6'b001111: begin // RRC
425
 
426
                     // rotate right circular
427
                     regfil[`reg_a] <=
428
                        (regfil[`reg_a] >> 1)+(regfil[`reg_a][0] << 7);
429
                     carry <= regfil[`reg_a][0];
430
                     state <= `cpus_fetchi; // Fetch next instruction
431
                     pc <= pc+1; // Next instruction byte
432
 
433
                  end
434
 
435
                  6'b011111: begin // RAR
436
 
437
                     // rotate right through carry
438
                     regfil[`reg_a] <= (regfil[`reg_a] >> 1)+(carry << 7);
439
                     carry <= regfil[`reg_a][0];
440
                     state <= `cpus_fetchi; // Fetch next instruction
441
                     pc <= pc+1; // Next instruction byte
442
 
443
                  end
444
 
445
                  6'b001001: begin // DAD B
446
 
447
                     // add BC to HL
448
                     { carry, regfil[`reg_h], regfil[`reg_l] } <=
449
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
450
                        (regfil[`reg_b] << 8)+regfil[`reg_c];
451
                     state <= `cpus_fetchi; // Fetch next instruction
452
                     pc <= pc+1; // Next instruction byte
453
 
454
                  end
455
 
456
                  6'b011001: begin // DAD D
457
 
458
                     // add DE to HL
459
                     { carry, regfil[`reg_h], regfil[`reg_l] } <=
460
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
461
                        (regfil[`reg_d] << 8)+regfil[`reg_e];
462
                     state <= `cpus_fetchi; // Fetch next instruction
463
                     pc <= pc+1; // Next instruction byte
464
 
465
                  end
466
 
467
                  6'b101001: begin // DAD H
468
 
469
                     // add HL to HL
470
                     { carry, regfil[`reg_h], regfil[`reg_l] } <=
471
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
472
                        (regfil[`reg_h] << 8)+regfil[`reg_l];
473
                     state <= `cpus_fetchi; // Fetch next instruction
474
                     pc <= pc+1; // Next instruction byte
475
 
476
                  end
477
 
478
                  6'b111001: begin // DAD SP
479
 
480
                     // add SP to HL
481
                     { carry, regfil[`reg_h], regfil[`reg_l] } <=
482
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+sp;
483
                     state <= `cpus_fetchi; // Fetch next instruction
484
                     pc <= pc+1; // Next instruction byte
485
 
486
                  end
487
 
488
                  6'b000011: begin // INX B
489
 
490
                     // increment BC, no flags set
491
                     regfil[`reg_b] <=
492
                        (((regfil[`reg_b] << 8)+regfil[`reg_c])+1)>>8;
493
                     regfil[`reg_c] <=
494
                        ((regfil[`reg_b] << 8)+regfil[`reg_c])+1;
495
                     state <= `cpus_fetchi; // Fetch next instruction
496
                     pc <= pc+1; // Next instruction byte
497
 
498
                  end
499
 
500
                  6'b010011: begin // INX D
501
 
502
                     // increment DE, no flags set
503
                     regfil[`reg_d] <=
504
                        (((regfil[`reg_d] << 8)+regfil[`reg_e])+1)>>8;
505
                     regfil[`reg_e] <=
506
                        ((regfil[`reg_d] << 8)+regfil[`reg_e])+1;
507
                     state <= `cpus_fetchi; // Fetch next instruction
508
                     pc <= pc+1; // Next instruction byte
509
 
510
                  end
511
 
512
                  6'b100011: begin // INX H
513
 
514
                     // increment HL, no flags set
515
                     regfil[`reg_h] <=
516
                        (((regfil[`reg_h] << 8)+regfil[`reg_l])+1)>>8;
517
                     regfil[`reg_l] <=
518
                        ((regfil[`reg_h] << 8)+regfil[`reg_l])+1;
519
                     state <= `cpus_fetchi; // Fetch next instruction
520
                     pc <= pc+1; // Next instruction byte
521
 
522
                  end
523
 
524
                  6'b110011: begin // INX SP
525
 
526
                     // increment SP, no flags set
527
                     sp <= sp+1;
528
                     state <= `cpus_fetchi; // Fetch next instruction
529
                     pc <= pc+1; // Next instruction byte
530
 
531
                  end
532
 
533
                  6'b001011: begin // DCX B
534
 
535
                     // decrement BC, no flags set
536
                     regfil[`reg_b] <=
537
                        (((regfil[`reg_b] << 8)+regfil[`reg_c])-1)>>8;
538
                     regfil[`reg_c] <=
539
                        ((regfil[`reg_b] << 8)+regfil[`reg_c])-1;
540
                     state <= `cpus_fetchi; // Fetch next instruction
541
                     pc <= pc+1; // Next instruction byte
542
 
543
                  end
544
 
545
                  6'b011011: begin // DCX D
546
 
547
                     // decrement DE, no flags set
548
                     regfil[`reg_d] <=
549
                        (((regfil[`reg_d] << 8)+regfil[`reg_e])-1)>>8;
550
                     regfil[`reg_e] <=
551
                        ((regfil[`reg_d] << 8)+regfil[`reg_e])-11;
552
                     state <= `cpus_fetchi; // Fetch next instruction
553
                     pc <= pc+1; // Next instruction byte
554
 
555
                  end
556
 
557
                  6'b101011: begin // DCX H
558
 
559
                     // decrement HL, no flags set
560
                     regfil[`reg_h] <=
561
                        (((regfil[`reg_h] << 8)+regfil[`reg_l])-1)>>8;
562
                     regfil[`reg_l] <=
563
                        ((regfil[`reg_h] << 8)+regfil[`reg_l])-1;
564
                     state <= `cpus_fetchi; // Fetch next instruction
565
                     pc <= pc+1; // Next instruction byte
566
 
567
                  end
568
 
569
                  6'b111011: begin // DCX SP
570
 
571
                     // decrement SP, no flags set
572
                     sp <= sp-1;
573
                     state <= `cpus_fetchi; // Fetch next instruction
574
                     pc <= pc+1; // Next instruction byte
575
 
576
                  end
577
 
578
                  6'b000001: begin // LXI B
579
 
580
                     raddrhold <= pc+1; // pick up after instruction
581
                     statesel <= `mac_readdtobc; // read double to BC
582
                     state <= `cpus_read;
583
                     pc <= pc+3; // skip
584
 
585
                  end
586
 
587
                  6'b010001: begin // LXI D
588
 
589
                     raddrhold <= pc+1; // pick up after instruction
590
                     statesel <= `mac_readdtode; // read double to DE
591
                     state <= `cpus_read;
592
                     pc <= pc+3; // skip
593
 
594
                  end
595
 
596
                  6'b100001: begin // LXI H
597
 
598
                     raddrhold <= pc+1; // pick up after instruction
599
                     statesel <= `mac_readdtohl; // read double to HL
600
                     state <= `cpus_read;
601
                     pc <= pc+3; // skip
602
 
603
                  end
604
 
605
                  6'b110001: begin // LXI SP
606
 
607
                     raddrhold <= pc+1; // pick up after instruction
608
                     pc <= pc+3; // skip
609
                     statesel <= `mac_readdtosp; // read double to SP
610
                     state <= `cpus_read;
611
                     pc <= pc+3; // skip
612
 
613
                  end
614
 
615
                  6'b000110, 6'b001110, 6'b010110, 6'b011110, 6'b100110,
616
                  6'b101110, 6'b110110, 6'b111110: begin // MVI
617
 
618
                     // move immediate to register
619 11 samiam9512
                     regd <= opcode[5:3]; // set destination register
620 2 samiam9512
                     raddrhold <= pc+1; // set pickup address
621 11 samiam9512
                     if (opcode[5:3] == `reg_m) begin // it's mvi m,imm
622 2 samiam9512
 
623 11 samiam9512
                        regd <= opcode[5:3]; // set destination register
624 2 samiam9512
                        // set destination address
625
                        waddrhold <= { regfil[`reg_h], regfil[`reg_l] };
626
                        statesel <= `mac_readbmtw; // read byte and move to write
627
 
628
                     end else
629
                        statesel <= `mac_readbmtr; // read byte and move to register
630
                     state <= `cpus_read;
631
                     pc <= pc+2; // advance over byte
632
 
633
                  end
634
 
635
                  6'b110010: begin // STA
636
 
637
                     wdatahold <= regfil[`reg_a]; // set write data
638
                     raddrhold <= pc+1; // set read address
639
                     statesel <= `mac_sta; // perform sta
640
                     state <= `cpus_read;
641
                     pc <= pc+3; // next
642
 
643
                  end
644
 
645
                  6'b111010: begin // LDA
646
 
647
                     raddrhold <= pc+1; // set read address
648
                     regd <= `reg_a; // set destination
649
                     statesel <= `mac_lda; // perform lda
650
                     state <= `cpus_read;
651
                     pc <= pc+3; // next
652
 
653
                  end
654
 
655
                  6'b100010: begin // SHLD
656
 
657
                     wdatahold <= regfil[`reg_l]; // set write data
658
                     wdatahold2 <= regfil[`reg_h];
659
                     raddrhold <= pc+1; // set read address
660
                     statesel <= `mac_shld; // perform SHLD
661
                     state <= `cpus_read;
662
                     pc <= pc+3; // next
663
 
664
                  end
665
 
666
                  6'b101010: begin // LHLD
667
 
668
                     raddrhold <= pc+1; // set read address
669
                     statesel <= `mac_lhld; // perform LHLD
670
                     state <= `cpus_read;
671
                     pc <= pc+3; // next
672
 
673
                  end
674
 
675
                  // the illegal opcodes behave as NOPs
676
 
677
                  6'b001000, 6'b010000, 6'b011000, 6'b100000, 6'b101000,
678
                  6'b110000, 6'b110000: begin
679
 
680
                     state <= `cpus_fetchi; // fetch next instruction
681
                     pc <= pc+1; // Next instruction byte
682
 
683
                  end
684
 
685
               endcase
686
 
687
            end
688
 
689
            2'b01: begin // 01: MOV instruction
690
 
691
               // Check its the halt instruction, which occupies the invalid
692
               // "MOV M,M" instruction.
693 11 samiam9512
               if (opcode == 8'b01110110) state <= `cpus_halt;
694 2 samiam9512
               // Otherwise, the 01 prefix is single instruction format.
695
               else begin
696
 
697
                  // Format 01DDDSSS
698
 
699
                  // Check memory source, use state if so
700 11 samiam9512
                  if (opcode[2:0] == `reg_m) begin
701 2 samiam9512
 
702
                     // place hl as address
703
                     raddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
704 11 samiam9512
                     regd <= opcode[5:3]; // set destination
705 2 samiam9512
                     statesel <= `mac_readbtoreg; // read byte to register
706
                     state <= `cpus_read;
707
 
708
                  // Check memory destination, use state if so
709
                  end else if (regd == `reg_m) begin
710
 
711
                     // place hl as address
712
                     waddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
713 11 samiam9512
                     wdatahold <= regfil[opcode[2:0]]; // place data to write
714 2 samiam9512
                     statesel <= `mac_writebyte; // write byte
715
                     state <= `cpus_write;
716
 
717
                  // otherwise simple register to register
718
                  end else begin
719
 
720 11 samiam9512
                     regfil[opcode[5:3]] <= regfil[opcode[2:0]];
721 2 samiam9512
                     state <= `cpus_fetchi; // Fetch next instruction
722
 
723
                  end
724
 
725
               end
726
               pc <= pc+1; // Next instruction byte
727
 
728
            end
729
 
730
            2'b10: begin // 10: Reg or mem to accumulator ops
731
 
732
               // 10 prefix is single instruction format
733
               aluopra <= regfil[`reg_a]; // load as alu a
734 11 samiam9512
               aluoprb <= regfil[opcode[2:0]]; // load as alu b
735
               alusel <= opcode[5:3]; // set alu operation from instruction
736 2 samiam9512
               alucin <= carry; // input carry
737 11 samiam9512
               if (opcode[2:0] == `reg_m) begin
738 2 samiam9512
 
739
                  // set read address
740
                  raddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
741
                  regd <= `reg_a; // set destination always a
742
                  statesel <= `mac_readbtoreg; // read byte to register
743
                  state <= `cpus_read;
744
 
745
               end else
746
                  state <= `cpus_alucb; // go to alu cycleback
747
               pc <= pc+1; // Next instruction byte
748
 
749
            end
750
 
751
            2'b11: begin // 11: jmp/call and others
752
 
753 11 samiam9512
               case (opcode[5:0]) // decode these instructions
754 2 samiam9512
 
755
                  6'b000101, 6'b010101, 6'b100101, 6'b110101: begin // PUSH
756
 
757
                     waddrhold <= sp-2; // write to stack
758
                     sp <= sp-2; // pushdown stack
759 11 samiam9512
                     case (opcode[5:4]) // register set
760 2 samiam9512
 
761
                        2'b00: { wdatahold2, wdatahold } <=
762
                                  { regfil[`reg_b], regfil[`reg_c] };
763
                        2'b01: { wdatahold2, wdatahold } <=
764
                                  { regfil[`reg_d], regfil[`reg_e] };
765
                        2'b10: { wdatahold2, wdatahold } <=
766
                                  { regfil[`reg_h], regfil[`reg_l] };
767
                        2'b11: { wdatahold2, wdatahold } <=
768
                                  { regfil[`reg_a], sign, zero, 1'b0, auxcar,
769 11 samiam9512
                                    1'b0, parity, 1'b1, carry };
770 2 samiam9512
 
771
                     endcase
772
                     statesel <= `mac_writedbyte; // write double byte
773
                     state <= `cpus_write;
774
                     pc <= pc+1; // Next instruction byte
775
 
776
                  end
777
 
778
                  6'b000001, 6'b010001, 6'b100001, 6'b110001: begin // POP
779
 
780 11 samiam9512
                     popdes <= opcode[5:4]; // set destination
781 2 samiam9512
                     raddrhold <= sp; // read from stack
782
                     sp <= sp+2; // pushup stack
783
                     statesel <= `mac_pop; // perform POP
784
                     state <= `cpus_read;
785
                     pc <= pc+1; // Next instruction byte
786
 
787
                  end
788
 
789
                  6'b101011: begin // XCHG
790
 
791
                     regfil[`reg_d] <= regfil[`reg_h];
792
                     regfil[`reg_e] <= regfil[`reg_l];
793
                     regfil[`reg_h] <= regfil[`reg_d];
794
                     regfil[`reg_l] <= regfil[`reg_e];
795
                     state <= `cpus_fetchi; // Fetch next instruction
796
                     pc <= pc+1; // Next instruction byte
797
 
798
                  end
799
 
800
                  6'b100011: begin // XTHL
801
 
802
                     raddrhold <= sp; // address SP for read
803
                     waddrhold <= sp; // address SP for write
804
                     wdatahold <= regfil[`reg_l]; // set data is HL
805
                     wdatahold2 <= regfil[`reg_h];
806
                     statesel <= `mac_xthl; // perform XTHL
807
                     state <= `cpus_read;
808
                     pc <= pc+1; // Next instruction byte
809
 
810
                  end
811
 
812
                  6'b111001: begin // SPHL
813
 
814
                     sp <= { regfil[`reg_h], regfil[`reg_l] };
815
                     state <= `cpus_fetchi; // Fetch next instruction
816
                     pc <= pc+1; // Next instruction byte
817
 
818
                  end
819
 
820
                  6'b000110, 6'b001110, 6'b010110, 6'b011110, 6'b100110,
821
                  6'b101110, 6'b110110,
822
                  6'b111110: begin // immediate arithmetic to accumulator
823
 
824
                     aluopra <= regfil[`reg_a]; // load as alu a
825 11 samiam9512
                     alusel <= opcode[5:3]; // set alu operation from instruction
826 2 samiam9512
                     alucin <= carry; // input carry
827
                     raddrhold <= pc+1; // read at PC
828
                     statesel <= `mac_accimm; // finish accumulator immediate
829
                     state <= `cpus_read;
830
                     pc <= pc+2; // skip immediate byte
831
 
832
                  end
833
 
834
                  6'b101001: begin // PCHL
835
 
836
                     state <= `cpus_fetchi; // Fetch next instruction
837
                     pc <= { regfil[`reg_h], regfil[`reg_l] };
838
 
839
                  end
840
 
841
                  6'b000011: begin // JMP
842
 
843
                     raddrhold <= pc+1; // pick up jump address
844
                     statesel <= `mac_jmp; // finish JMP
845
                     state <= `cpus_read;
846
 
847
                  end
848
 
849
                  6'b000010, 6'b001010, 6'b010010, 6'b011010, 6'b100010,
850
                  6'b101010, 6'b110010, 6'b111010: begin // Jcc
851
 
852
                     raddrhold <= pc+1; // pick up jump address
853
                     statesel <= `mac_jmp; // finish JMP
854
                     // choose continue or read according to condition
855 11 samiam9512
                     case (opcode[5:3]) // decode flag cases
856 2 samiam9512
 
857
                        3'b000: if (zero) state <= `cpus_fetchi;
858
                                else state <= `cpus_read;
859
                        3'b001: if (!zero) state <= `cpus_fetchi;
860
                                else state <= `cpus_read;
861
                        3'b010: if (carry) state <= `cpus_fetchi;
862
                                else state <= `cpus_read;
863
                        3'b011: if (!carry) state <= `cpus_fetchi;
864
                                else state <= `cpus_read;
865
                        3'b100: if (parity) state <= `cpus_fetchi;
866
                                else state <= `cpus_read;
867
                        3'b101: if (!parity) state <= `cpus_fetchi;
868
                                else state <= `cpus_read;
869
                        3'b110: if (sign) state <= `cpus_fetchi;
870
                                else state <= `cpus_read;
871
                        3'b111: if (!sign) state <= `cpus_fetchi;
872
                                else state <= `cpus_read;
873
 
874
                     endcase
875
                     pc <= pc+3; // advance after jump for false
876
 
877
                  end
878
 
879
                  6'b001101: begin // CALL
880
 
881
                     raddrhold <= pc+1; // pick up call address
882
                     waddrhold <= sp-2; // place address on stack
883 9 samiam9512
                     // if interrupt cycle, use current pc, else use address
884
                     // after call
885
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
886
                     else { wdatahold2, wdatahold } <= pc+3;
887 2 samiam9512
                     sp <= sp-2; // pushdown stack
888
                     statesel <= `mac_call; // finish CALL
889
                     state <= `cpus_read;
890
 
891
                  end
892
 
893
                  6'b000100, 6'b001100, 6'b010100, 6'b011100, 6'b100100,
894
                  6'b101100, 6'b110100, 6'b111100: begin // Ccc
895
 
896
                     raddrhold <= pc+1; // pick up call address
897
                     waddrhold <= sp-2; // place address on stack
898
                     { wdatahold2, wdatahold } <= pc+3; // of address after call
899
                     sp <= sp-2; // pushdown stack
900
                     statesel <= `mac_call; // finish CALL
901
                     // choose continue or read according to condition
902 11 samiam9512
                     case (opcode[5:3]) // decode flag cases
903 2 samiam9512
 
904
                        3'b000: if (zero) state <= `cpus_fetchi;
905
                                else state <= `cpus_read;
906
                        3'b001: if (!zero) state <= `cpus_fetchi;
907
                                else state <= `cpus_read;
908
                        3'b010: if (carry) state <= `cpus_fetchi;
909
                                else state <= `cpus_read;
910
                        3'b011: if (!carry) state <= `cpus_fetchi;
911
                                else state <= `cpus_read;
912
                        3'b100: if (parity) state <= `cpus_fetchi;
913
                                else state <= `cpus_read;
914
                        3'b101: if (!parity) state <= `cpus_fetchi;
915
                                else state <= `cpus_read;
916
                        3'b110: if (sign) state <= `cpus_fetchi;
917
                                else state <= `cpus_read;
918
                        3'b111: if (!sign) state <= `cpus_fetchi;
919
                                else state <= `cpus_read;
920
 
921
                     endcase
922
                     pc <= pc+3; // advance after jump for false
923
 
924
                  end
925
 
926
                  6'b001001: begin // RET
927
 
928
                     raddrhold <= sp; // read from stack
929
                     sp <= sp+2; // pushup stack
930
                     statesel <= `mac_jmp; // finish JMP
931
                     state <= `cpus_read;
932
 
933
                  end
934
 
935
                  6'b000000, 6'b001000, 6'b010000, 6'b011000, 6'b100000,
936
                  6'b101000, 6'b110000, 6'b111000: begin // Rcc
937
 
938
                     raddrhold <= sp; // read from stack
939
                     sp <= sp+2; // pushup stack
940
                     statesel <= `mac_jmp; // finish JMP
941
                     // choose read or continue according to condition
942 11 samiam9512
                     case (opcode[5:3]) // decode flag cases
943 2 samiam9512
 
944
                        3'b000: if (zero) state <= `cpus_fetchi;
945
                                else state <= `cpus_read;
946
                        3'b001: if (!zero) state <= `cpus_fetchi;
947
                                else state <= `cpus_read;
948
                        3'b010: if (carry) state <= `cpus_fetchi;
949
                                else state <= `cpus_read;
950
                        3'b011: if (!carry) state <= `cpus_fetchi;
951
                                else state <= `cpus_read;
952
                        3'b100: if (parity) state <= `cpus_fetchi;
953
                                else state <= `cpus_read;
954
                        3'b101: if (!parity) state <= `cpus_fetchi;
955
                                else state <= `cpus_read;
956
                        3'b110: if (sign) state <= `cpus_fetchi;
957
                                else state <= `cpus_read;
958
                        3'b111: if (!sign) state <= `cpus_fetchi;
959
                                else state <= `cpus_read;
960
 
961
                     endcase
962
                     pc <= pc+1; // Next instruction byte
963
 
964
                  end
965
 
966
                  6'b000111, 6'b001111, 6'b010111, 6'b011111, 6'b100111,
967
                  6'b101111, 6'b110111, 6'b111111: begin // RST
968
 
969 11 samiam9512
                     pc <= opcode & 8'b00111000; // place restart value in PC
970 2 samiam9512
                     waddrhold <= sp-2; // place address on stack
971 9 samiam9512
                     // if interrupt cycle, use current pc, else use address
972
                     // after call
973
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
974
                     else { wdatahold2, wdatahold } <= pc+3;
975 2 samiam9512
                     { wdatahold2, wdatahold } <= pc+1; // of address after call
976
                     sp <= sp-2; // pushdown stack
977
                     statesel <= `mac_writedbyte; // finish RST
978
                     state <= `cpus_write; // write to stack
979
 
980
                  end
981
 
982
                  6'b111011: begin // EI
983
 
984 11 samiam9512
                     eienb <= 1'b1; // set delayed interrupt enable
985 2 samiam9512
                     state <= `cpus_fetchi; // Fetch next instruction
986
                     pc <= pc+1; // Next instruction byte
987
 
988
                  end
989
 
990
                  6'b110011: begin // DI
991
 
992
                     ei <= 1'b0;
993
                     state <= `cpus_fetchi; // Fetch next instruction
994
                     pc <= pc+1; // Next instruction byte
995
 
996
                  end
997
 
998
                  6'b011011: begin // IN p
999
 
1000
                     raddrhold <= pc+1; // pick up byte I/O address
1001
                     pc <= pc+2; // next
1002
                     statesel <= `mac_in; // finish IN
1003
                     state <= `cpus_read;
1004
                     pc <= pc+2; // Next instruction byte
1005
 
1006
                  end
1007
 
1008
                  6'b010011: begin // OUT p
1009
 
1010
                     raddrhold <= pc+1; // pick up byte I/O address
1011
                     pc <= pc+2; // next
1012
                     statesel <= `mac_out; // finish OUT
1013
                     state <= `cpus_read;
1014
                     pc <= pc+2; // Next instruction byte
1015
 
1016
                  end
1017
 
1018
                  // the illegal opcodes behave as NOPs
1019
 
1020
                  6'b001011, 6'b011001, 6'b011101, 6'b101101,
1021
                  6'b111101: begin
1022
 
1023
                     state <= `cpus_fetchi; // fetch next instruction
1024
                     pc <= pc+2; // Next instruction byte
1025
 
1026
                  end
1027
 
1028
               endcase
1029
 
1030
            end
1031
 
1032
         endcase
1033
 
1034
      end
1035
 
1036
      // Follow states. These state handlers implement the following cycles past
1037
      // M1, or primary fetch state.
1038
 
1039
      //
1040
      // single byte write, writes wdatahold to the waddrhold address
1041
      //
1042
 
1043
      `cpus_write: begin
1044
 
1045
         addr <= waddrhold; // place address on output
1046
         waddrhold <= waddrhold+1; // next address
1047
         datao <= wdatahold; // set data to output
1048
         wdatahold <= wdatahold2; // next data
1049
         dataeno <= 1; // enable output data
1050
         state <= `cpus_write2; // next state
1051
 
1052
      end
1053
 
1054
      `cpus_write2: begin // continue write #2
1055
 
1056
         writemem <= 1; // enable write memory data
1057
         state <= `cpus_write3; // idle one cycle for write
1058
 
1059
      end
1060
 
1061
      `cpus_write3: begin // continue write #3
1062
 
1063
         if (!waitr) begin // no wait selected, otherwise cycle
1064
 
1065
            writemem <= 0; // disable write memory data
1066
            state <= `cpus_write4; // idle hold time
1067
 
1068
         end
1069
 
1070
      end
1071
 
1072
      `cpus_write4: begin // continue write #4
1073
 
1074
         dataeno <= 0; // disable output data
1075
         state <= nextstate; // get next macro state
1076
         statesel <= statesel+1; // and index next in macro 
1077
 
1078
      end
1079
 
1080
      //
1081
      // single byte read, reads rdatahold from the raddrhold address
1082
      //
1083
 
1084
      `cpus_read: begin
1085
 
1086
         addr <= raddrhold; // place address on output
1087
         raddrhold <= raddrhold+1; // next address
1088 9 samiam9512
         if (intcyc) inta <= 1; // activate interrupt acknowledge
1089 18 samiam9512
         else readmem <= 1; // activate memory read
1090 2 samiam9512
         state <= `cpus_read2; // next state
1091
 
1092
      end
1093
 
1094
      `cpus_read2: begin // continue read #2
1095
 
1096 18 samiam9512
         // wait one cycle
1097
         state <= `cpus_read3; // next state
1098
 
1099
      end
1100
 
1101
      `cpus_read3: begin // continue read #3
1102
 
1103 2 samiam9512
         if (!waitr) begin // no wait selected, otherwise cycle
1104
 
1105
            rdatahold2 <= rdatahold; // shift data
1106
            rdatahold <= data; // read new data
1107
            readmem <= 0; // deactivate instruction memory read
1108 9 samiam9512
            inta <= 0; // deactivate interrupt acknowledge
1109 2 samiam9512
            state <= nextstate; // get next macro state
1110
            statesel <= statesel+1; // and index next in macro 
1111
 
1112
         end
1113
 
1114
      end
1115
 
1116
      `cpus_pop: begin // finish POP instruction
1117
 
1118
         case (popdes) // register set
1119
 
1120
            2'b00: { regfil[`reg_b], regfil[`reg_c] } <=
1121
                      { rdatahold, rdatahold2 };
1122
            2'b01: { regfil[`reg_d], regfil[`reg_e] } <=
1123
                      { rdatahold, rdatahold2 };
1124
            2'b10: { regfil[`reg_h], regfil[`reg_l] } <=
1125
                      { rdatahold, rdatahold2 };
1126
            2'b11: begin
1127
 
1128
               regfil[`reg_a] <= rdatahold;
1129
               sign <= rdatahold2 >> 7&1;
1130
               zero <= rdatahold2 >> 6&1;
1131
               auxcar <= rdatahold2 >> 4&1;
1132
               parity <= rdatahold2 >> 2&1;
1133
               carry <= rdatahold2 >> 1&1;
1134
 
1135
            end
1136
 
1137
         endcase
1138
         state <= `cpus_fetchi; // Fetch next instruction
1139
 
1140
      end
1141
 
1142
      `cpus_jmp: begin // jump address
1143
 
1144
         state <= `cpus_fetchi; // and return to instruction fetch
1145
         pc <= { rdatahold, rdatahold2 };
1146
 
1147
      end
1148
 
1149
      `cpus_in: begin // input single byte to A
1150
 
1151
         addr <= rdatahold; // place I/O address on address lines
1152
         readio <= 1; // set read I/O
1153
         state <= `cpus_in2; // continue
1154
 
1155
      end
1156
 
1157
      `cpus_in2: begin // input single byte to A #2
1158 18 samiam9512
 
1159
         // wait one cycle
1160
         state <= `cpus_in3; // continue
1161 2 samiam9512
 
1162 18 samiam9512
      end
1163 2 samiam9512
 
1164 18 samiam9512
      `cpus_in3: begin // input single byte to A #3
1165
 
1166
         if (!waitr) begin // no wait selected, otherwise cycle
1167
 
1168
            regfil[`reg_a] <= data; // place input data
1169
            readio <= 0; // clear read I/O
1170
            state <= `cpus_fetchi; // Fetch next instruction
1171
 
1172
         end
1173
 
1174 2 samiam9512
      end
1175
 
1176
      `cpus_out: begin // output single byte from A
1177
 
1178
         addr <= rdatahold; // place address on output
1179
         datao <= regfil[`reg_a]; // set data to output
1180
         dataeno <= 1; // enable output data
1181
         state <= `cpus_out2; // next state
1182
 
1183
      end
1184
 
1185
      `cpus_out2: begin // continue out #2
1186
 
1187
         writeio <= 1; // enable write I/O data
1188
         state <= `cpus_out3; // idle one cycle for write
1189
 
1190
      end
1191
 
1192
      `cpus_out3: begin // continue out #3
1193
 
1194 18 samiam9512
         if (!waitr) begin // no wait selected, otherwise cycle
1195 2 samiam9512
 
1196 18 samiam9512
            writeio <= 0; // disable write I/O data
1197
            state <= `cpus_out4; // idle hold time
1198
 
1199
         end
1200
 
1201 2 samiam9512
      end
1202
 
1203
      `cpus_out4: begin // continue write #4
1204
 
1205
         dataeno <= 0; // disable output data
1206
         state <= `cpus_fetchi; // Fetch next instruction
1207
 
1208
      end
1209
 
1210
      `cpus_halt: begin // Halt waiting for interrupt
1211
 
1212 9 samiam9512
         // If there is an interrupt request and interrupts are enabled, then we
1213
         // can leave halt. Otherwise we stay here.
1214
         if (intr&&ei) state <= `cpus_fetchi; // Fetch next instruction
1215
         else state <= `cpus_halt;
1216
 
1217 2 samiam9512
 
1218
      end
1219
 
1220
      `cpus_movtr: begin // move to register
1221
 
1222
         regfil[regd] <= rdatahold; // place data
1223
         state <= nextstate; // get next macro state
1224
         statesel <= statesel+1; // and index next in macro 
1225
 
1226
      end
1227
 
1228
      `cpus_alucb: begin // alu cycleback
1229
 
1230
         regfil[`reg_a] <= alures; // place alu result back to A
1231
         carry <= alucout; // place carry
1232
         sign <= alusout; // place sign
1233
         zero <= aluzout; // place zero
1234
         parity <= alupar; // place parity
1235
         auxcar <= aluaxc; // place auxiliary carry
1236
         state <= `cpus_fetchi; // and return to instruction fetch
1237
 
1238
      end
1239
 
1240
      `cpus_indcb: begin // inr/dcr cycleback
1241
 
1242
         regfil[regd] <= alures; // place alu result back to source/dest
1243
         sign <= alures[7]; // place sign
1244
         zero <= aluzout; // place zero
1245
         parity <= alupar; // place parity
1246
         auxcar <= aluaxc; // place auxiliary carry
1247
         state <= `cpus_fetchi; // and return to instruction fetch
1248
 
1249
      end
1250
 
1251
      `cpus_movmtbc: begin // finish LXI B
1252
 
1253
         regfil[`reg_b] <= rdatahold; // place upper
1254
         regfil[`reg_c] <= rdatahold2; // place lower
1255
         state <= `cpus_fetchi; // and return to instruction fetch
1256
 
1257
      end
1258
 
1259
      `cpus_movmtde: begin // finish LXI D
1260
 
1261
         regfil[`reg_d] <= rdatahold; // place upper
1262
         regfil[`reg_e] <= rdatahold2; // place lower
1263
         state <= `cpus_fetchi; // and return to instruction fetch
1264
 
1265
      end
1266
 
1267
      `cpus_movmthl: begin // finish LXI H
1268
 
1269
         regfil[`reg_h] <= rdatahold; // place upper
1270
         regfil[`reg_l] <= rdatahold2; // place lower
1271
         state <= `cpus_fetchi; // and return to instruction fetch
1272
 
1273
      end
1274
 
1275
      `cpus_movmtsp: begin // finish LXI SP
1276
 
1277
         sp <= { rdatahold, rdatahold2 }; // place
1278
         state <= `cpus_fetchi; // and return to instruction fetch
1279
 
1280
      end
1281
 
1282
      `cpus_movrtw: begin // move read to write
1283
 
1284
         wdatahold <= rdatahold; // move read to write data
1285
         state <= nextstate; // get next macro state
1286
         statesel <= statesel+1; // and index next in macro 
1287
 
1288
      end
1289
 
1290
      `cpus_movrtwa: begin // move read data to write address
1291
 
1292
         waddrhold <= { rdatahold, rdatahold2 };
1293
         state <= nextstate; // get next macro state
1294
         statesel <= statesel+1; // and index next in macro 
1295
 
1296
      end
1297
 
1298
      `cpus_movrtra: begin // move read data to read address
1299
 
1300
         raddrhold <= { rdatahold, rdatahold2 };
1301
         state <= nextstate; // get next macro state
1302
         statesel <= statesel+1; // and index next in macro 
1303
 
1304
      end
1305
 
1306
      `cpus_lhld: begin // load HL from read data
1307
 
1308
         regfil[`reg_l] <= rdatahold2; // low
1309
         regfil[`reg_h] <= rdatahold; // high
1310
         state <= nextstate; // get next macro state
1311
         statesel <= statesel+1; // and index next in macro 
1312
 
1313
      end
1314
 
1315
      `cpus_accimm: begin
1316
 
1317
         aluoprb <= rdatahold; // load as alu b
1318
         state <= `cpus_alucb; // go to alu cycleback
1319
 
1320
      end
1321
 
1322
      `cpus_daa: begin
1323
 
1324
         if (regfil[`reg_a][7:4] > 9 || carry) begin
1325
 
1326
            { carry, regfil[`reg_a] } <= regfil[`reg_a]+8'h60;
1327
 
1328
         end
1329
         state <= `cpus_fetchi; // and return to instruction fetch
1330
 
1331
      end
1332
 
1333
      default: state <= 5'bx;
1334
 
1335
   endcase
1336
 
1337
   // Enable drive for data output
1338
   assign data = dataeno ? datao: 8'bz;
1339
 
1340
   //
1341
   // State macro generator
1342
   //
1343
   // This ROM contains series of state execution lists that perform various
1344
   // tasks, usually involving reads or writes.
1345
   //
1346
 
1347
   always @(statesel) case (statesel)
1348
 
1349
      // mac_writebyte: write a byte
1350
 
1351
       1: nextstate = `cpus_fetchi; // fetch next instruction
1352
 
1353
      // mac_readbtoreg: read a byte, place in register
1354
 
1355
       2: nextstate = `cpus_movtr; // move to register
1356
       3: nextstate = `cpus_fetchi; // Fetch next instruction
1357
 
1358
      // mac_readdtobc: read double byte to BC
1359
 
1360
       4: nextstate = `cpus_read; // get high byte
1361
       5: nextstate = `cpus_movmtbc; // place in BC
1362
 
1363
      // mac_readdtode: read double byte to DE
1364
 
1365
       6: nextstate = `cpus_read; // get high byte
1366
       7: nextstate = `cpus_movmtde; // place in DE
1367
 
1368
      // mac_readdtohl: read double byte to HL
1369
 
1370
       8: nextstate = `cpus_read; // get high byte
1371
       9: nextstate = `cpus_movmthl; // place in HL
1372
 
1373
      // mac_readdtosp: read double byte to SP
1374
 
1375
      10: nextstate = `cpus_read; // get high byte
1376
      11: nextstate = `cpus_movmtsp; // place in SP
1377
 
1378
      // mac_readbmtw: read byte and move to write
1379
 
1380
      12: nextstate = `cpus_movrtw; // move read to write 
1381
      13: nextstate = `cpus_fetchi; // Fetch next instruction
1382
 
1383
      // mac_readbmtr: read byte and move to register
1384
 
1385
      14: nextstate = `cpus_movtr; // place in register
1386
      15: nextstate = `cpus_fetchi; // Fetch next instruction
1387
 
1388
      // mac_sta: STA
1389
 
1390
      16: nextstate = `cpus_read; // read high byte
1391
      17: nextstate = `cpus_movrtwa; // move read to write address
1392
      18: nextstate = `cpus_write; // write to destination
1393
      19: nextstate = `cpus_fetchi; // Fetch next instruction
1394
 
1395
      // mac_lda: LDA
1396
 
1397
      20: nextstate = `cpus_read; // read high byte
1398
      21: nextstate = `cpus_movrtra; // move read to write address
1399
      22: nextstate = `cpus_read; // read byte
1400
      23: nextstate = `cpus_movtr; // move to register
1401
      24: nextstate = `cpus_fetchi; // Fetch next instruction
1402
 
1403
      // mac_shld: SHLD
1404
 
1405
      25: nextstate = `cpus_read; // read high byte
1406
      26: nextstate = `cpus_movrtwa; // move read to write address
1407
      27: nextstate = `cpus_write; // write to destination low
1408
      28: nextstate = `cpus_write; // write to destination high
1409
      29: nextstate = `cpus_fetchi; // Fetch next instruction
1410
 
1411
      // mac_lhld: LHLD
1412
 
1413
      30: nextstate = `cpus_read; // read high byte
1414
      31: nextstate = `cpus_movrtra; // move read to write address
1415
      32: nextstate = `cpus_read; // read byte low
1416
      33: nextstate = `cpus_read; // read byte high
1417
      34: nextstate = `cpus_lhld; // move to register
1418
      35: nextstate = `cpus_fetchi; // Fetch next instruction
1419
 
1420
      // mac_writedbyte: write double byte
1421
 
1422
      36: nextstate = `cpus_write; // double write
1423
      37: nextstate = `cpus_fetchi; // then fetch
1424
 
1425
      // mac_pop: POP
1426
 
1427
      38: nextstate = `cpus_read; // double it
1428
      39: nextstate = `cpus_pop; // then finish
1429
 
1430
      // mac_xthl: XTHL
1431
 
1432
      40: nextstate = `cpus_read; // double it
1433
      41: nextstate = `cpus_write; // then write
1434
      42: nextstate = `cpus_write; // double it
1435
      43: nextstate = `cpus_movmthl; // place word in hl
1436
 
1437
      // mac_accimm: accumulator immediate
1438
 
1439
      44: nextstate = `cpus_accimm; // finish
1440
 
1441
      // mac_jmp: JMP
1442
 
1443
      45: nextstate = `cpus_read; // double read
1444
      46: nextstate = `cpus_jmp; // then go pc
1445
 
1446
      // mac_call: CALL
1447
 
1448
      47: nextstate = `cpus_read; // double read
1449
      48: nextstate = `cpus_write; // then write
1450
      49: nextstate = `cpus_write; // double write
1451
      50: nextstate = `cpus_jmp; // then go to that
1452
 
1453
      // mac_in: IN
1454
 
1455
      51: nextstate = `cpus_in; // go to IN after getting that
1456
 
1457
      // mac_out: OUT
1458
 
1459
      52: nextstate = `cpus_out; // go to OUT after getting that
1460
 
1461
      // mac_rst: RST
1462
 
1463
      53: nextstate = `cpus_write; // double write
1464
      54: nextstate = `cpus_jmp; // then go to that
1465
 
1466
      default nextstate = 6'bx; // other states never reached
1467
 
1468
   endcase
1469
 
1470
endmodule
1471
 
1472
//
1473
// Alu module
1474
//
1475
// Finds arithmetic operations needed. Latches on the positive edge of the
1476
// clock. There are 8 different types of operations, which come from bits
1477
// 3-5 of the instruction.
1478
//
1479
 
1480
module alu(res, opra, oprb, cin, cout, zout, sout, parity, auxcar, sel);
1481
 
1482
   input  [7:0] opra;   // Input A
1483
   input  [7:0] oprb;   // Input B
1484
   input        cin;    // Carry in
1485
   output       cout;   // Carry out
1486
   output       zout;   // Zero out
1487
   output       sout;   // Sign out
1488
   output       parity; // parity
1489
   output       auxcar; // auxiliary carry
1490
   input  [2:0] sel;    // Operation select
1491
   output [7:0] res;    // Result of alu operation
1492
 
1493
   reg       cout;   // Carry out
1494
   reg       zout;   // Zero out
1495
   reg       sout;   // sign out
1496
   reg       parity; // parity
1497
   reg       auxcar; // auxiliary carry
1498
   reg [7:0] resi;   // Result of alu operation intermediate
1499
   reg [7:0] res;    // Result of alu operation
1500
 
1501
   always @(opra, oprb, cin, sel, res, resi) begin
1502
 
1503
      case (sel)
1504
 
1505
         `aluop_add: begin // add
1506
 
1507
            { cout, resi } = opra+oprb; // find result and carry
1508
            auxcar = (opra[3:0]+oprb[3:0]) >> 4 & 1; // find auxiliary carry
1509
 
1510
         end
1511
         `aluop_adc: begin // adc
1512
 
1513
            { cout, resi } = opra+oprb+cin; // find result and carry
1514
            auxcar = (opra[3:0]+oprb[3:0]+cin) >> 4 & 1; // find auxiliary carry
1515
 
1516
         end
1517
         `aluop_sub, `aluop_cmp: begin // sub/cmp
1518
 
1519
            { cout, resi } = opra-oprb; // find result and carry
1520
            auxcar = (opra[3:0]-oprb[3:0]) >> 4 & 1; // find auxiliary borrow
1521
 
1522
         end
1523
         `aluop_sbb: begin // sbb
1524
 
1525
            { cout, resi } = opra-oprb-cin; // find result and carry
1526
            auxcar = (opra[3:0]-oprb[3:0]-cin >> 4) & 1; // find auxiliary borrow
1527
 
1528
         end
1529
         `aluop_and: begin // ana
1530
 
1531
            { cout, resi } = {1'b0, opra&oprb}; // find result and carry
1532
            auxcar = 0; // clear auxillary carry
1533
 
1534
          end
1535
         `aluop_xor: begin // xra
1536
 
1537
            { cout, resi } = {1'b0, opra^oprb}; // find result and carry
1538
            auxcar = 0; // clear auxillary carry
1539
 
1540
         end
1541
         `aluop_or:  begin // ora
1542
 
1543
            { cout, resi } = {1'b0, opra|oprb}; // find result and carry
1544
            auxcar = 0; // clear auxillary carry
1545
 
1546
         end
1547
 
1548
      endcase
1549
 
1550
      if (sel != `aluop_cmp) res = resi; else res = opra;
1551
      zout <= ~|resi; // set zero flag from result
1552
      sout <= resi[7]; // set sign flag from result
1553
      parity <= ~^resi; // set parity flag from result
1554
 
1555
   end
1556
 
1557
endmodule

powered by: WebSVN 2.1.0

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