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

Subversion Repositories cpu8080

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

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

powered by: WebSVN 2.1.0

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