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

Subversion Repositories cpu8080

[/] [cpu8080/] [tags/] [update/] [project/] [m8080.v] - Blame information for rev 33

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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