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

Subversion Repositories cpu8080

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

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

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

powered by: WebSVN 2.1.0

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