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

Subversion Repositories cpu8080

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

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

powered by: WebSVN 2.1.0

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