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

Subversion Repositories cpu8080

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

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

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

powered by: WebSVN 2.1.0

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