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

Subversion Repositories cpu8080

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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