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

Subversion Repositories cpu8080

[/] [cpu8080/] [trunk/] [project/] [m8080.v] - Rev 33

Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
// Company:                                                                   //  
// Engineer:       Scott Moore                                                //
//                                                                            //
// Create Date:    11:45:32 09/04/2006                                        // 
// Design Name:                                                               // 
// Module Name:    cpu8080                                                    //
// Project Name:   cpu8080                                                    //
// Target Devices: xc3c200, xc3s1000                                          //
// Tool versions:                                                             //
// Description:                                                               //
//                                                                            //
//     Executes the 8080 instruction set. It is designed to be an internal    //
//     cell. Each of the I/Os are positive logic, and all signals are         //
//     constant with the exception of the data bus. The control signals are   //
//     fully decoded (unlike the orignal 8080), and features read and write   //
//     signals for both memory and I/O space. The I/O space is an 8 bit       //
//     address as in the original 8080. It does NOT echo the lower 8 bits to  //
//     the higher 8 bits, as was the practice in some systems.                //
//                                                                            //
//     Like the original 8080, the interrupt vectoring is fully external. The //
//     the external controller forces a full instruction onto the data bus.   //
//     The sequence begins with the assertion of interrupt request. The CPU   //
//     will then assert interrupt acknowledge, then it will run a special     //
//     read cycle with inta asserted for each cycle of a possibly             //
//     multibyte instruction. This matches the original 8080, which typically //
//     used single byte restart instructions to form a simple interrupt       //
//     controller, but was capable of full vectoring via insertion of a jump, //
//     call or similar instruction.                                           //
//                                                                            //
//     Note that the interrupt vector instruction should branch. This is      //
//     because the PC gets changed by the vector instruction, so if it does   //
//     not branch, it will have skipped a number of bytes after the interrupt //
//     equivalent to the vector instruction. The only instructions that       //
//     should really be used to vector are jmp, rst and call instructions.    //
//     Specifically, rst and call instruction compensate for the pc movement  //
//     by putting the pc unmodified on the stack.                             //
//                                                                            //
//     The memory, I/O and interrupt fetches all obey a simple clocking       //
//     sequence as follows. The CPU uses the positive clock edge to assert    //
//     and sample signals and data. The external logic theoretically uses the //
//     negative edge to check signal assertions and sample data, but it can   //
//     either use the negative edge, or actually be asynronous logic.         //
//                                                                            //
//     A standard read sequence is as follows:                                //
//                                                                            //
//     1. At the positive clock edge, readmem, readio or readint is asserted. //
//     2. At the negative clock edge (or immediately), the external memory    //
//        places data onto the data bus.                                      //
//     3. We hold automatically for one cycle.                                //
//     4. At the next positive clock edge, the data is sampled, and the read  //
//        Signal is deasserted.                                               //
//                                                                            //
//     A standard write sequence is as follows:                               //
//                                                                            //
//     1. At the positive edge, data is asserted on the data bus.             //
//     2. At the next postive clock edge, writemem or writeio is asserted.    //
//     3. At the next positive clock edge, writemem or writeio is deasserted. //
//     4. At the next positive edge, the data is deasserted.                  //
//                                                                            //
// Dependencies:                                                              //
//                                                                            //
// Revision:                                                                  //
// Revision 0.01 - File Created                                               //
// Additional Comments:                                                       //
//                                                                            //
//  Modifications, commented by 'CNS' below, NOV-12-2006 Chris N. Strahm      //
//	(1)	Fixed warnings due to bit width truncations, assignment sizes.        //
//  (2) Changed tristate data bus to din,dout. Better for internal FPGA use.  // 
//  (3) Removed waitr line, hard assigned to 0.  Not much use in FPGA's.      //
//  (4) Implemented INTR hardware vectoring.  Orig 8080 external INT vector   //
//      scheme not useful for FPGAs with other soft core perfs. Added inputs: //
//      INTR[1] - Vector/Reset to 0008H                                       // 
//      INTR[2] - Vector/Reset to 0010H                                       // 
//      INTR[3] - Vector/Reset to 0018H                                       //
//      INTR[4] - Vector/Reset to 0020H                                       //
//      INTR[5] - Vector/Reset to 0028H                                       //
//      INTR[6] - Vector/Reset to 0030H                                       //
//      INTR[7] - Vector/Reset to 0038H                                       //
//  Note: Unused intr lines can just be assigned/wired to 0.                  //
//  Note: inta is still provided as a common ack to any intr.                 //
//  Note: Program execution origin at 0H should now jump to >= 0040H to begin //
//        main code to skip over the interrupt vector locations.              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
 
`timescale 1ns / 1ps
 
//
// CPU states
//
 
`define cpus_idle     6'h00 // Idle
`define cpus_fetchi   6'h01 // Instruction fetch
`define cpus_fetchi2  6'h02 // Instruction fetch 2
`define cpus_fetchi3  6'h03 // Instruction fetch 3
`define cpus_fetchi4  6'h04 // Instruction fetch 4
`define cpus_halt     6'h05 // Halt (wait for interrupt)
`define cpus_alucb    6'h06 // alu cycleback
`define cpus_indcb    6'h07 // inr/dcr cycleback
`define cpus_movmtbc  6'h08 // Move memory to bc
`define cpus_movmtde  6'h09 // Move memory to de
`define cpus_movmthl  6'h0a // Move memory to hl
`define cpus_movmtsp  6'h0b // Move memory to sp
`define cpus_lhld     6'h0c // LHLD
`define cpus_jmp      6'h0d // JMP
`define cpus_write    6'h0e // write byte
`define cpus_write2   6'h0f // write byte #2
`define cpus_write3   6'h10 // write byte #3
`define cpus_write4   6'h11 // write byte #4
`define cpus_read     6'h12 // read byte
`define cpus_read2    6'h13 // read byte #2
`define cpus_read3    6'h14 // read byte #3
`define cpus_pop      6'h15 // POP completion
`define cpus_in       6'h16 // IN
`define cpus_in2      6'h17 // IN #2
`define cpus_in3      6'h18 // IN #3
`define cpus_out      6'h19 // OUT
`define cpus_out2     6'h1a // OUT #2
`define cpus_out3     6'h1b // OUT #3
`define cpus_out4     6'h1c // OUT #4
`define cpus_movtr    6'h1d // move to register
`define cpus_movrtw   6'h1e // move read to write
`define cpus_movrtwa  6'h1f // move read to write address
`define cpus_movrtra  6'h20 // move read to read address
`define cpus_accimm   6'h21 // accumulator immediate operations
`define cpus_daa      6'h22 // DAA completion
 
//
// Register numbers
//
 
`define reg_b 3'b000 // B
`define reg_c 3'b001 // C
`define reg_d 3'b010 // D
`define reg_e 3'b011 // E
`define reg_h 3'b100 // H
`define reg_l 3'b101 // L
`define reg_m 3'b110 // M
`define reg_a 3'b111 // A
 
//
// ALU operations
//
 
`define aluop_add 3'b000 // add
`define aluop_adc 3'b001 // add with carry in
`define aluop_sub 3'b010 // subtract
`define aluop_sbb 3'b011 // subtract with borrow in
`define aluop_and 3'b100 // and
`define aluop_xor 3'b101 // xor
`define aluop_or  3'b110 // or
`define aluop_cmp 3'b111 // compare
 
//
// State macros
//
`define mac_writebyte  1  // write a byte
`define mac_readbtoreg 2  // read a byte, place in register
`define mac_readdtobc  4  // read double byte to BC
`define mac_readdtode  6  // read double byte to DE
`define mac_readdtohl  8  // read double byte to HL
`define mac_readdtosp  10 // read double byte to SP
`define mac_readbmtw   12 // read byte and move to write
`define mac_readbmtr   14 // read byte and move to register
`define mac_sta        16 // STA
`define mac_lda        20 // LDA
`define mac_shld       25 // SHLD
`define mac_lhld       30 // LHLD
`define mac_writedbyte 36 // write double byte
`define mac_pop        38 // POP
`define mac_xthl       40 // XTHL
`define mac_accimm     44 // accumulator immediate
`define mac_jmp        45 // JMP
`define mac_call       47 // CALL
`define mac_in         51 // IN
`define mac_out        52 // OUT
`define mac_rst        53 // RST
 
//
// Reset/Int Opcodes  (CNS)
//
`define opcode_reset_0 8'b11000111 // reset int vector to 0000H
`define opcode_reset_1 8'b11001111 // reset int vector to 0008H
`define opcode_reset_2 8'b11010111 // reset int vector to 0010H
`define opcode_reset_3 8'b11011111 // reset int vector to 0018H
`define opcode_reset_4 8'b11100111 // reset int vector to 0020H
`define opcode_reset_5 8'b11101111 // reset int vector to 0028H
`define opcode_reset_6 8'b11110111 // reset int vector to 0030H
`define opcode_reset_7 8'b11111111 // reset int vector to 0038H
 
 
module M8080  (addr,     // Address out
               dout,     // Data Output bus
               din,      // Data Input  bus
               readmem,  // Memory read   
               writemem, // Memory write
               readio,   // Read I/O space
               writeio,  // Write I/O space
               intr,     // Interrupt request bus, hard wire vector select [7:1] CNS
               inta,     // Interrupt acknowledge, common to any intr 
               reset,    // Reset
//               waitr,    // Wait request  CNS
               clock	 // Clock
               );   // System clock
 
   output [15:0] addr;
   input  [7:0] din;
   output [7:0] dout;
   output readmem;
   output writemem;
   output readio;
   output writeio;
   input  [7:1] intr; // CNS
   output inta;
//   input  waitr;   CNS
   input  reset;
   input  clock; // synthesis clock 
 
   wire   waitr = 1'b0;		// no extra wait states, lock low, CNS
 
   // Output or input lines that need to be registered
 
   reg           readmem;
   reg           writemem;
   reg    [15:0] pc;
   reg    [15:0] addr;
   reg           readio;
   reg           writeio;
   reg           inta;
   reg    [15:0] sp;
 
   // Local registers
 
   reg    [5:0]  state;       // CPU state machine
   reg    [2:0]  regd;        // Destination register
   reg    [7:0]  datao;       // Data output register
//   reg           dataeno;     // Enable output data CNS
   reg    [15:0] waddrhold;   // address holding for write
   reg    [15:0] raddrhold;   // address holding for read
   reg    [7:0]  wdatahold;   // single byte write data holding
   reg    [7:0]  wdatahold2;  // single byte write data holding
   reg    [7:0]  rdatahold;   // single byte read data holding
   reg    [7:0]  rdatahold2;  // single byte read data holding
   reg    [1:0]  popdes;      // POP destination code
   reg    [5:0]  statesel;    // state map selector
   reg    [5:0]  nextstate;   // next state output
   reg           eienb;       // interrupt enable delay shift reg
   reg    [7:0]  opcode;      // opcode holding
 
   // Register file. Note that 3'b110 (6) is not used, and is the code for a
   // memory reference.
 
   reg    [7:0]  regfil[0:7];
 
   // The flags are represented individually
 
   reg           carry; 	// carry bit
   reg           auxcar; 	// auxiliary carry bit
   reg           sign; 		// sign bit
   reg           zero; 		// zero bit
   reg           parity; 	// parity bit
   reg           ei; 		// interrupt enable
   reg           intcyc; 	// in interrupt cycle
 
   // ALU communication
 
   wire   [7:0]  alures;  // result
   reg    [7:0]  aluopra; // left side operand
   reg    [7:0]  aluoprb; // right side operand
   reg           alucin;  // carry in
   wire          alucout; // carry out
   wire          alupar;  // parity out
   wire          aluaxc;  // auxiliary carry
   reg    [2:0]  alusel;  // alu operational select
   wire 		 aluzout; // CNS
   wire			 alusout; // CNS   
 
   // Instantiate the ALU
 
   alu alu(alures, aluopra, aluoprb, alucin, alucout, aluzout, alusout, alupar, aluaxc, alusel);
 
   always @(posedge clock)
      if (reset) begin // syncronous reset actions
 
      state   <= `cpus_fetchi; // Clear CPU state to initial fetch
      pc      <= 0; // reset program counter to 1st location
//      dataeno <= 0; // get off the data bus CNS
      readmem <= 0; // all signals out false
      writemem<= 0;
      readio  <= 0;
      writeio <= 0;
      inta    <= 0;
      intcyc  <= 0;
      ei      <= 1;
      eienb   <= 0;
 
   end else case (state)
 
      `cpus_fetchi: begin // start of instruction fetch
 
         // if any interrupt request is on, enter interrupt cycle, else exit it now
         if (ei&&(intr[1]||intr[2]||intr[3]||intr[4]||intr[5]||intr[6]||intr[7])) begin	// CNS
//         if (intr&&ei) begin
 
            intcyc <= 1;	// enter interrupt cycle
            inta <= 1; 		// activate interrupt acknowledge
            ei <= 0; 		// disable interrupts
 
         end else begin
 
            intcyc <= 0; 	// leave interrupt cycle
            readmem <= 1; 	// activate instruction memory read
 
         end
 
         addr <= pc; 		// place current program count on output
         if (eienb) ei <=1; // process delayed interrupt enable
         eienb <=0; 		// reset interrupt enabler
         state <= `cpus_fetchi2; // next state
 
      end
 
      `cpus_fetchi2: begin // wait
 
         state <= `cpus_fetchi3; // next state
 
       end
 
      `cpus_fetchi3: begin // complete instruction memory read
 
         if (!waitr) begin // no wait selected, otherwise cycle
 
			// CNS: If we have an intr, then force the opcode to rst#
			// else read the op code from the data input as usual. 
			if (intcyc) begin		// for an int cycle
				if (intr[1]) opcode <= `opcode_reset_1;	// int vector to 0008H
				if (intr[2]) opcode <= `opcode_reset_2;	// int vector to 0010H
				if (intr[3]) opcode <= `opcode_reset_3;	// int vector to 0018H
				if (intr[4]) opcode <= `opcode_reset_4;	// int vector to 0020H
				if (intr[5]) opcode <= `opcode_reset_5;	// int vector to 0028H
				if (intr[6]) opcode <= `opcode_reset_6;	// int vector to 0030H
				if (intr[7]) opcode <= `opcode_reset_7;	// int vector to 0038H
                intcyc <= 0; 		// we will kill the intcyc here, don't need it further
			end else opcode <= din;	// latch/read opcode CNS
 
            readmem <= 0; 			// Deactivate instruction memory read
            inta <= 0; 				// Deactivate interrupt acknowledge
            state <= `cpus_fetchi4; // next state
 
         end
 
      end
 
      `cpus_fetchi4: begin // complete instruction memory read
 
         // We split off the instructions into 4 groups. Most of the 8080
         // instructions are in the MOV and ACC operations class.
 
         case (opcode[7:6]) // Decode top level
 
            2'b00: begin // 00: Data transfers and others
 
               case (opcode[5:0]) // decode these instructions
 
                  6'b000000: begin // NOP
 
                     // yes, do nothing
 
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte  CNS
 
                  end
 
                  6'b110111: begin // STC
 
                     carry <= 1; // set carry flag
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte CNS
 
                  end
 
                  6'b111111: begin // CMC
 
                     carry <= ~carry; // complement carry flag
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte CNS
 
                  end
 
                  6'b101111: begin // CMA
 
                     regfil[`reg_a] <= ~regfil[`reg_a]; // complement accumulator
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte CNS
 
                  end
 
                  6'b100111: begin // DAA
 
                     // decimal adjust accumulator, or remove by carry any 
                     // results in nybbles greater than 9
 
                     if (regfil[`reg_a][3:0] > 9 || auxcar) begin
 
                        { carry, regfil[`reg_a] } <= regfil[`reg_a]+ 3'b110;  // CNS 6
                        auxcar <= ((regfil[`reg_a][3:0]+6 >> 4) & 1'b1) ? 1'b1:1'b0; // cns
 
                     end
                     state <= `cpus_daa; // finish DAA
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000100, 6'b001100, 6'b010100, 6'b011100, 6'b100100, 
                  6'b101100, 6'b110100, 6'b111100, 6'b000101, 6'b001101, 
                  6'b010101, 6'b011101, 6'b100101, 6'b101101, 6'b110101, 
                  6'b111101: begin // INR/DCR
 
                     regd <= opcode[5:3]; // get source/destination reg
                     aluopra <= regfil[opcode[5:3]]; // load as alu a
                     aluoprb <= 1; // load 1 as alu b
                     if (opcode[0]) alusel <= `aluop_sub; // set subtract
                     else alusel <= `aluop_add; // set add
                     state <= `cpus_indcb; // go inr/dcr cycleback
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000010, 6'b010010: begin // STAX
 
                     wdatahold <= regfil[`reg_a]; // place A as source
                     if (opcode[4]) // use DE pair
                        waddrhold <= regfil[`reg_d]<<8|regfil[`reg_d];
                     else // use BC pair
                        waddrhold <= regfil[`reg_b] << 8|regfil[`reg_c];
                     statesel <= `mac_writebyte; // write byte
                     state <= `cpus_write;
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b001010, 6'b011010: begin // LDAX
 
                     regd <= `reg_a; // set A as destination
                     if (opcode[4]) // use DE pair
                        raddrhold <= regfil[`reg_d]<<8|regfil[`reg_d];
                     else // use BC pair
                        raddrhold <= regfil[`reg_b]<<8|regfil[`reg_c];
                     statesel <= `mac_readbtoreg; // read byte to register
                     state <= `cpus_read;
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000111: begin // RLC
 
                     // rotate left circular
                     { carry, regfil[`reg_a] } <= 
                        (regfil[`reg_a] << 1)+regfil[`reg_a][7];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b010111: begin // RAL
 
                     // rotate left through carry
                     { carry, regfil[`reg_a] } <= (regfil[`reg_a] << 1)+carry;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b001111: begin // RRC
 
                     // rotate right circular
                     regfil[`reg_a] <= 
                        (regfil[`reg_a] >> 1)+(regfil[`reg_a][0] << 7);
                     carry <= regfil[`reg_a][0];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b011111: begin // RAR
 
                     // rotate right through carry
                     regfil[`reg_a] <= (regfil[`reg_a] >> 1)+(carry << 7);
                     carry <= regfil[`reg_a][0];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b001001: begin // DAD B
 
                     // add BC to HL
                     { carry, regfil[`reg_h], regfil[`reg_l] } <= 
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
                        (regfil[`reg_b] << 8)+regfil[`reg_c];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b011001: begin // DAD D
 
                     // add DE to HL
                     { carry, regfil[`reg_h], regfil[`reg_l] } <= 
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
                        (regfil[`reg_d] << 8)+regfil[`reg_e];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b101001: begin // DAD H
 
                     // add HL to HL
                     { carry, regfil[`reg_h], regfil[`reg_l] } <= 
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+
                        (regfil[`reg_h] << 8)+regfil[`reg_l];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b111001: begin // DAD SP
 
                     // add SP to HL
                     { carry, regfil[`reg_h], regfil[`reg_l] } <= 
                        (regfil[`reg_h] << 8)+regfil[`reg_l]+sp;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000011: begin // INX B
 
                     // increment BC, no flags set
                     regfil[`reg_b] <= 
                        (((regfil[`reg_b] << 8)+regfil[`reg_c])+1'b1)>>8;
                     regfil[`reg_c] <= 
                        ((regfil[`reg_b] << 8)+regfil[`reg_c])+1'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b010011: begin // INX D
 
                     // increment DE, no flags set
                     regfil[`reg_d] <= 
                        (((regfil[`reg_d] << 8)+regfil[`reg_e])+1'b1)>>8;
                     regfil[`reg_e] <= 
                        ((regfil[`reg_d] << 8)+regfil[`reg_e])+1'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b100011: begin // INX H
 
                     // increment HL, no flags set
                     regfil[`reg_h] <= 
                        (((regfil[`reg_h] << 8)+regfil[`reg_l])+1'b1)>>8;
                     regfil[`reg_l] <= 
                        ((regfil[`reg_h] << 8)+regfil[`reg_l])+1'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b110011: begin // INX SP
 
                     // increment SP, no flags set
                     sp <= sp + 16'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b001011: begin // DCX B
 
                     // decrement BC, no flags set
                     regfil[`reg_b] <= 
                        (((regfil[`reg_b] << 8)+regfil[`reg_c]) - 8'b1)>>8;
                     regfil[`reg_c] <= 
                        ((regfil[`reg_b] << 8)+regfil[`reg_c])- 8'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc + 1'b1; // Next instruction byte
 
                  end
 
                  6'b011011: begin // DCX D
 
                     // decrement DE, no flags set
                     regfil[`reg_d] <= 
                        (((regfil[`reg_d] << 8)+regfil[`reg_e]) - 8'b1)>>8;
                     regfil[`reg_e] <= 
                        ((regfil[`reg_d] << 8)+regfil[`reg_e])- 8'd11;	// cns 11
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc + 1'b1; // Next instruction byte
 
                  end
 
                  6'b101011: begin // DCX H
 
                     // decrement HL, no flags set
                     regfil[`reg_h] <= 
                        (((regfil[`reg_h] << 8)+regfil[`reg_l])- 8'b1)>>8;
                     regfil[`reg_l] <= 
                        ((regfil[`reg_h] << 8)+regfil[`reg_l]) - 8'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b111011: begin // DCX SP
 
                     // decrement SP, no flags set
                     sp <= sp - 16'b1;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000001: begin // LXI B
 
                     raddrhold <= pc+1'b1; // pick up after instruction
                     statesel <= `mac_readdtobc; // read double to BC
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // skip
 
                  end
 
                  6'b010001: begin // LXI D
 
                     raddrhold <= pc+1'b1; // pick up after instruction
                     statesel <= `mac_readdtode; // read double to DE
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // skip
 
                  end
 
                  6'b100001: begin // LXI H
 
                     raddrhold <= pc+1'b1; // pick up after instruction
                     statesel <= `mac_readdtohl; // read double to HL
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // skip
 
                  end
 
                  6'b110001: begin // LXI SP
 
                     raddrhold <= pc+1'b1; // pick up after instruction
                     pc <= pc + 16'h3; // skip
                     statesel <= `mac_readdtosp; // read double to SP
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // skip
 
                  end
 
                  6'b000110, 6'b001110, 6'b010110, 6'b011110, 6'b100110, 
                  6'b101110, 6'b110110, 6'b111110: begin // MVI
 
                     // move immediate to register
                     regd <= opcode[5:3]; // set destination register
                     raddrhold <= pc+1'b1; // set pickup address
                     if (opcode[5:3] == `reg_m) begin // it's mvi m,imm
 
                        regd <= opcode[5:3]; // set destination register
                        // set destination address
                        waddrhold <= { regfil[`reg_h], regfil[`reg_l] };
                        statesel <= `mac_readbmtw; // read byte and move to write
 
                     end else 
                        statesel <= `mac_readbmtr; // read byte and move to register
                     state <= `cpus_read;
                     pc <= pc + 16'h2; // advance over byte
 
                  end
 
                  6'b110010: begin // STA
 
                     wdatahold <= regfil[`reg_a]; // set write data
                     raddrhold <= pc+1'b1; // set read address
                     statesel <= `mac_sta; // perform sta
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // next
 
                  end
 
                  6'b111010: begin // LDA
 
                     raddrhold <= pc+1'b1; // set read address
                     regd <= `reg_a; // set destination
                     statesel <= `mac_lda; // perform lda
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // next
 
                  end
 
                  6'b100010: begin // SHLD
 
                     wdatahold <= regfil[`reg_l]; // set write data
                     wdatahold2 <= regfil[`reg_h];
                     raddrhold <= pc+1'b1; // set read address
                     statesel <= `mac_shld; // perform SHLD
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // next
 
                  end
 
                  6'b101010: begin // LHLD
 
                     raddrhold <= pc+1'b1; // set read address
                     statesel <= `mac_lhld; // perform LHLD
                     state <= `cpus_read;
                     pc <= pc + 16'h3; // next
 
                  end
 
                  // the illegal opcodes behave as NOPs
 
                  6'b001000, 6'b010000, 6'b011000, 6'b100000, 6'b101000, 
                  6'b110000, 6'b110000: begin 
 
                     state <= `cpus_fetchi; // fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
               endcase
 
            end
 
            2'b01: begin // 01: MOV instruction
 
               // Check its the halt instruction, which occupies the invalid
               // "MOV M,M" instruction.
               if (opcode == 8'b01110110) state <= `cpus_halt;
               // Otherwise, the 01 prefix is single instruction format.
               else begin
 
                  // Format 01DDDSSS
 
                  // Check memory source, use state if so
                  if (opcode[2:0] == `reg_m) begin
 
                     // place hl as address
                     raddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
                     regd <= opcode[5:3]; // set destination
                     statesel <= `mac_readbtoreg; // read byte to register
                     state <= `cpus_read;
 
                  // Check memory destination, use state if so
                  end else if (regd == `reg_m) begin
 
                     // place hl as address
                     waddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
                     wdatahold <= regfil[opcode[2:0]]; // place data to write
                     statesel <= `mac_writebyte; // write byte
                     state <= `cpus_write;
 
                  // otherwise simple register to register
                  end else begin
 
                     regfil[opcode[5:3]] <= regfil[opcode[2:0]];
                     state <= `cpus_fetchi; // Fetch next instruction
 
                  end
 
               end
               pc <= pc+1'b1; // Next instruction byte
 
            end
 
            2'b10: begin // 10: Reg or mem to accumulator ops
 
               // 10 prefix is single instruction format
               aluopra <= regfil[`reg_a]; // load as alu a
               aluoprb <= regfil[opcode[2:0]]; // load as alu b
               alusel <= opcode[5:3]; // set alu operation from instruction
               alucin <= carry; // input carry
               if (opcode[2:0] == `reg_m) begin
 
                  // set read address
                  raddrhold <= regfil[`reg_h]<<8|regfil[`reg_l];
                  regd <= `reg_a; // set destination always a
                  statesel <= `mac_readbtoreg; // read byte to register
                  state <= `cpus_read;
 
               end else
                  state <= `cpus_alucb; // go to alu cycleback
               pc <= pc+1'b1; // Next instruction byte
 
            end
 
            2'b11: begin // 11: jmp/call and others
 
               case (opcode[5:0]) // decode these instructions
 
                  6'b000101, 6'b010101, 6'b100101, 6'b110101: begin // PUSH
 
                     waddrhold <= sp - 16'h2; // write to stack
                     sp <= sp - 16'h2; // pushdown stack
                     case (opcode[5:4]) // register set
 
                        2'b00: { wdatahold2, wdatahold } <= 
                                  { regfil[`reg_b], regfil[`reg_c] };
                        2'b01: { wdatahold2, wdatahold } <= 
                                  { regfil[`reg_d], regfil[`reg_e] };
                        2'b10: { wdatahold2, wdatahold } <= 
                                  { regfil[`reg_h], regfil[`reg_l] };
                        2'b11: { wdatahold2, wdatahold } <= 
                                  { regfil[`reg_a], sign, zero, 1'b0, auxcar, 
                                    1'b0, parity, 1'b1, carry };
 
                     endcase
                     statesel <= `mac_writedbyte; // write double byte
                     state <= `cpus_write;
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000001, 6'b010001, 6'b100001, 6'b110001: begin // POP
 
                     popdes <= opcode[5:4]; // set destination
                     raddrhold <= sp; // read from stack
                     sp <= sp + 16'h2; // pushup stack
                     statesel <= `mac_pop; // perform POP
                     state <= `cpus_read;
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b101011: begin // XCHG
 
                     regfil[`reg_d] <= regfil[`reg_h];
                     regfil[`reg_e] <= regfil[`reg_l];
                     regfil[`reg_h] <= regfil[`reg_d];
                     regfil[`reg_l] <= regfil[`reg_e];
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b100011: begin // XTHL
 
                     raddrhold <= sp; // address SP for read
                     waddrhold <= sp; // address SP for write
                     wdatahold <= regfil[`reg_l]; // set data is HL
                     wdatahold2 <= regfil[`reg_h];
                     statesel <= `mac_xthl; // perform XTHL
                     state <= `cpus_read;
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b111001: begin // SPHL
 
                     sp <= { regfil[`reg_h], regfil[`reg_l] };
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000110, 6'b001110, 6'b010110, 6'b011110, 6'b100110, 
                  6'b101110, 6'b110110, 
                  6'b111110: begin // immediate arithmetic to accumulator
 
                     aluopra <= regfil[`reg_a]; // load as alu a
                     alusel <= opcode[5:3]; // set alu operation from instruction
                     alucin <= carry; // input carry
                     raddrhold <= pc + 1'b1; // read at PC
                     statesel <= `mac_accimm; // finish accumulator immediate
                     state <= `cpus_read;
                     pc <= pc + 16'h2; // skip immediate byte
 
                  end
 
                  6'b101001: begin // PCHL
 
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= { regfil[`reg_h], regfil[`reg_l] };
 
                  end
 
                  6'b000011: begin // JMP
 
                     raddrhold <= pc+1'b1; // pick up jump address
                     statesel <= `mac_jmp; // finish JMP
                     state <= `cpus_read;
 
                  end
 
                  6'b000010, 6'b001010, 6'b010010, 6'b011010, 6'b100010, 
                  6'b101010, 6'b110010, 6'b111010: begin // Jcc
 
                     raddrhold <= pc+1'b1; // pick up jump address
                     statesel <= `mac_jmp; // finish JMP
                     // choose continue or read according to condition
                     case (opcode[5:3]) // decode flag cases
 
                        3'b000: if (zero) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b001: if (!zero) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b010: if (carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b011: if (!carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b100: if (parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b101: if (!parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b110: if (sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b111: if (!sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
 
                     endcase
                     pc <= pc + 16'h3; // advance after jump for false
 
                  end
 
                  6'b001101: begin // CALL
 
                     raddrhold <= pc+1'b1; // pick up call address
                     waddrhold <= sp - 16'h2; // place address on stack
                     // if interrupt cycle, use current pc, else use address
                     // after call
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
                     else { wdatahold2, wdatahold } <= pc + 16'h3;
                     sp <= sp - 16'h2; // pushdown stack
                     statesel <= `mac_call; // finish CALL
                     state <= `cpus_read;
 
                  end
 
                  6'b000100, 6'b001100, 6'b010100, 6'b011100, 6'b100100, 
                  6'b101100, 6'b110100, 6'b111100: begin // Ccc
 
                     raddrhold <= pc + 1'b1; // pick up call address
                     waddrhold <= sp - 16'h2; // place address on stack
                     { wdatahold2, wdatahold } <= pc + 16'h3; // of address after call
                     sp <= sp - 16'h2; // pushdown stack
                     statesel <= `mac_call; // finish CALL
                     // choose continue or read according to condition
                     case (opcode[5:3]) // decode flag cases
 
                        3'b000: if (zero) state <= `cpus_fetchi; 
                                else state <= `cpus_read;
                        3'b001: if (!zero) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b010: if (carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b011: if (!carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b100: if (parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b101: if (!parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b110: if (sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b111: if (!sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
 
                     endcase
                     pc <= pc + 16'h3; // advance after jump for false
 
                  end
 
                  6'b001001: begin // RET
 
                     raddrhold <= sp; // read from stack
                     sp <= sp + 16'h2; // pushup stack
                     statesel <= `mac_jmp; // finish JMP
                     state <= `cpus_read;
 
                  end
 
                  6'b000000, 6'b001000, 6'b010000, 6'b011000, 6'b100000, 
                  6'b101000, 6'b110000, 6'b111000: begin // Rcc
 
                     raddrhold <= sp; // read from stack
                     sp <= sp + 16'h2; // pushup stack
                     statesel <= `mac_jmp; // finish JMP
                     // choose read or continue according to condition
                     case (opcode[5:3]) // decode flag cases
 
                        3'b000: if (zero) state <= `cpus_fetchi; 
                                else state <= `cpus_read;
                        3'b001: if (!zero) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b010: if (carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b011: if (!carry) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b100: if (parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b101: if (!parity) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b110: if (sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
                        3'b111: if (!sign) state <= `cpus_fetchi;
                                else state <= `cpus_read;
 
                     endcase
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b000111, 6'b001111, 6'b010111, 6'b011111, 6'b100111, 
                  6'b101111, 6'b110111, 6'b111111: begin // RST
 
                     pc <= opcode & 8'b00111000; // place restart value in PC
                     waddrhold <= sp - 16'h2; // place address on stack
                     // if interrupt cycle, use current pc, else use address
                     // after call
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
                     else { wdatahold2, wdatahold } <= pc + 16'h3; // cns 
                     { wdatahold2, wdatahold } <= pc + 1'b1; // of address after call CNS
                     sp <= sp - 16'h2; // pushdown stack CNS
                     statesel <= `mac_writedbyte; // finish RST
                     state <= `cpus_write; // write to stack
 
                  end
 
                  6'b111011: begin // EI
 
                     eienb <= 1'b1; // set delayed interrupt enable
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b110011: begin // DI
 
                     ei <= 1'b0;
                     state <= `cpus_fetchi; // Fetch next instruction
                     pc <= pc+1'b1; // Next instruction byte
 
                  end
 
                  6'b011011: begin // IN p
 
                     raddrhold <= pc+1'b1; // pick up byte I/O address
                     pc <= pc + 2'b10; // next
                     statesel <= `mac_in; // finish IN
                     state <= `cpus_read;
                     pc <= pc + 2'b10; // Next instruction byte
 
                  end
 
                  6'b010011: begin // OUT p
 
                     raddrhold <= pc+1'b1; // pick up byte I/O address
                     pc <= pc + 2'b10; // next
                     statesel <= `mac_out; // finish OUT
                     state <= `cpus_read;
                     pc <= pc + 2'b10; // Next instruction byte
 
                  end
 
                  // the illegal opcodes behave as NOPs
 
                  6'b001011, 6'b011001, 6'b011101, 6'b101101, 
                  6'b111101: begin
 
                     state <= `cpus_fetchi; // fetch next instruction
                     pc <= pc + 2'b10; // Next instruction byte, cns 2
 
                  end
 
               endcase
 
            end
 
         endcase
 
      end
 
      // Follow states. These state handlers implement the following cycles past
      // M1, or primary fetch state.
 
      //
      // single byte write, writes wdatahold to the waddrhold address
      //
 
      `cpus_write: begin
 
         addr <= waddrhold; // place address on output
         waddrhold <= waddrhold + 1'b1; // next address
         datao <= wdatahold; // set data to output
         wdatahold <= wdatahold2; // next data
//         dataeno <= 1; // enable output data CNS
         state <= `cpus_write2; // next state
 
      end
 
      `cpus_write2: begin // continue write #2
 
         writemem <= 1; // enable write memory data
         state <= `cpus_write3; // idle one cycle for write
 
      end
 
      `cpus_write3: begin // continue write #3
 
         if (!waitr) begin // no wait selected, otherwise cycle
 
            writemem <= 0; // disable write memory data
            state <= `cpus_write4; // idle hold time
 
         end
 
      end
 
      `cpus_write4: begin // continue write #4
 
//         dataeno <= 0; // disable output data CNS
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro 
 
      end
 
      //
      // single byte read, reads rdatahold from the raddrhold address
      //
 
      `cpus_read: begin
 
         addr <= raddrhold; // place address on output
         raddrhold <= raddrhold + 1'b1; // next address
         if (intcyc) inta <= 1; // activate interrupt acknowledge
         else readmem <= 1; // activate memory read
         state <= `cpus_read2; // next state
 
      end
 
      `cpus_read2: begin // continue read #2
 
         // wait one cycle
         state <= `cpus_read3; // next state
 
      end
 
      `cpus_read3: begin // continue read #3
 
         if (!waitr) begin // no wait selected, otherwise cycle
 
            rdatahold2 <= rdatahold; // shift data
            rdatahold <= din; // read new data CNS
            readmem <= 0; // deactivate instruction memory read
            inta <= 0; // deactivate interrupt acknowledge
            state <= nextstate; // get next macro state
            statesel <= statesel+1'b1; // and index next in macro 
 
         end
 
      end
 
      `cpus_pop: begin // finish POP instruction
 
         case (popdes) // register set
 
            2'b00: { regfil[`reg_b], regfil[`reg_c] } <= 
                      { rdatahold, rdatahold2 };
            2'b01: { regfil[`reg_d], regfil[`reg_e] } <= 
                      { rdatahold, rdatahold2 };
            2'b10: { regfil[`reg_h], regfil[`reg_l] } <= 
                      { rdatahold, rdatahold2 };
            2'b11: begin
 
               regfil[`reg_a] <= rdatahold;
               sign   <= ((rdatahold2 >> 7)& 1'b1) ? 1'b1:1'b0;
               zero   <= ((rdatahold2 >> 6)& 1'b1) ? 1'b1:1'b0;
               auxcar <= ((rdatahold2 >> 4)& 1'b1) ? 1'b1:1'b0;
               parity <= ((rdatahold2 >> 2)& 1'b1) ? 1'b1:1'b0;
               carry  <= ((rdatahold2 >> 0)& 1'b1) ? 1'b1:1'b0;
 
            end
 
         endcase
         state <= `cpus_fetchi; // Fetch next instruction
 
      end
 
      `cpus_jmp: begin // jump address
 
         state <= `cpus_fetchi; // and return to instruction fetch
         pc <= { rdatahold, rdatahold2 };
 
      end
 
      `cpus_in: begin // input single byte to A
 
         addr <= rdatahold; // place I/O address on address lines
         readio <= 1; // set read I/O
         state <= `cpus_in2; // continue
 
      end
 
      `cpus_in2: begin // input single byte to A #2
 
         // wait one cycle
         state <= `cpus_in3; // continue
 
      end
 
      `cpus_in3: begin // input single byte to A #3
 
         if (!waitr) begin // no wait selected, otherwise cycle
 
            regfil[`reg_a] <= din; // place input data CNS
            readio <= 0; // clear read I/O
            state <= `cpus_fetchi; // Fetch next instruction
 
         end
 
      end
 
      `cpus_out: begin // output single byte from A
 
         addr <= rdatahold; // place address on output
         datao <= regfil[`reg_a]; // set data to output
//         dataeno <= 1; // enable output data CNS
         state <= `cpus_out2; // next state
 
      end
 
      `cpus_out2: begin // continue out #2
 
         writeio <= 1; // enable write I/O data
         state <= `cpus_out3; // idle one cycle for write
 
      end
 
      `cpus_out3: begin // continue out #3
 
         if (!waitr) begin // no wait selected, otherwise cycle
 
            writeio <= 0; // disable write I/O data
            state <= `cpus_out4; // idle hold time
 
         end
 
      end
 
      `cpus_out4: begin // continue write #4
 
//         dataeno <= 0; // disable output data CNS
         state <= `cpus_fetchi; // Fetch next instruction
 
      end
 
      `cpus_halt: begin // Halt waiting for interrupt
 
         // If there is an interrupt request and interrupts are enabled, then we
         // can leave halt. Otherwise we stay here.
         if (ei&&(intr[1]||intr[2]||intr[3]||intr[4]||intr[5]||intr[6]||intr[7])) state <= `cpus_fetchi; // Fetch next instruction	// CNS
//         if (intr&&ei) state <= `cpus_fetchi; // Fetch next instruction
         else state <= `cpus_halt;
 
 
      end
 
      `cpus_movtr: begin // move to register
 
         regfil[regd] <= rdatahold; // place data
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro 
 
      end
 
      `cpus_alucb: begin // alu cycleback
 
         regfil[`reg_a] <= alures; // place alu result back to A
         carry <= alucout; // place carry
         sign <= alusout; // place sign
         zero <= aluzout; // place zero
         parity <= alupar; // place parity
         auxcar <= aluaxc; // place auxiliary carry
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_indcb: begin // inr/dcr cycleback
 
         regfil[regd] <= alures; // place alu result back to source/dest
         sign <= alures[7]; // place sign
         zero <= aluzout; // place zero
         parity <= alupar; // place parity
         auxcar <= aluaxc; // place auxiliary carry
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_movmtbc: begin // finish LXI B
 
         regfil[`reg_b] <= rdatahold; // place upper
         regfil[`reg_c] <= rdatahold2; // place lower
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_movmtde: begin // finish LXI D
 
         regfil[`reg_d] <= rdatahold; // place upper
         regfil[`reg_e] <= rdatahold2; // place lower
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_movmthl: begin // finish LXI H
 
         regfil[`reg_h] <= rdatahold; // place upper
         regfil[`reg_l] <= rdatahold2; // place lower
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_movmtsp: begin // finish LXI SP
 
         sp <= { rdatahold, rdatahold2 }; // place
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      `cpus_movrtw: begin // move read to write
 
         wdatahold <= rdatahold; // move read to write data
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro cns
 
      end
 
      `cpus_movrtwa: begin // move read data to write address
 
         waddrhold <= { rdatahold, rdatahold2 };
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro cns
 
      end
 
      `cpus_movrtra: begin // move read data to read address
 
         raddrhold <= { rdatahold, rdatahold2 };
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro cns
 
      end
 
      `cpus_lhld: begin // load HL from read data
 
         regfil[`reg_l] <= rdatahold2; // low
         regfil[`reg_h] <= rdatahold; // high
         state <= nextstate; // get next macro state
         statesel <= statesel+1'b1; // and index next in macro CNS
 
      end
 
      `cpus_accimm: begin
 
         aluoprb <= rdatahold; // load as alu b
         state <= `cpus_alucb; // go to alu cycleback
 
      end
 
      `cpus_daa: begin
 
         if (regfil[`reg_a][7:4] > 9 || carry) begin
 
            { carry, regfil[`reg_a] } <= regfil[`reg_a]+8'h60;
 
         end
         state <= `cpus_fetchi; // and return to instruction fetch
 
      end
 
      default: state <= 5'bx;
 
   endcase
 
   // Enable drive for data output
   assign dout = datao; // CNS
 
   //
   // State macro generator
   //
   // This ROM contains series of state execution lists that perform various
   // tasks, usually involving reads or writes.
   //
 
   always @(statesel) case (statesel)
 
      // mac_writebyte: write a byte
 
       1: nextstate = `cpus_fetchi; // fetch next instruction
 
      // mac_readbtoreg: read a byte, place in register
 
       2: nextstate = `cpus_movtr; // move to register
       3: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_readdtobc: read double byte to BC
 
       4: nextstate = `cpus_read; // get high byte
       5: nextstate = `cpus_movmtbc; // place in BC
 
      // mac_readdtode: read double byte to DE
 
       6: nextstate = `cpus_read; // get high byte
       7: nextstate = `cpus_movmtde; // place in DE
 
      // mac_readdtohl: read double byte to HL
 
       8: nextstate = `cpus_read; // get high byte
       9: nextstate = `cpus_movmthl; // place in HL
 
      // mac_readdtosp: read double byte to SP
 
      10: nextstate = `cpus_read; // get high byte
      11: nextstate = `cpus_movmtsp; // place in SP
 
      // mac_readbmtw: read byte and move to write
 
      12: nextstate = `cpus_movrtw; // move read to write 
      13: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_readbmtr: read byte and move to register
 
      14: nextstate = `cpus_movtr; // place in register
      15: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_sta: STA
 
      16: nextstate = `cpus_read; // read high byte
      17: nextstate = `cpus_movrtwa; // move read to write address
      18: nextstate = `cpus_write; // write to destination
      19: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_lda: LDA
 
      20: nextstate = `cpus_read; // read high byte
      21: nextstate = `cpus_movrtra; // move read to write address
      22: nextstate = `cpus_read; // read byte
      23: nextstate = `cpus_movtr; // move to register
      24: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_shld: SHLD
 
      25: nextstate = `cpus_read; // read high byte
      26: nextstate = `cpus_movrtwa; // move read to write address
      27: nextstate = `cpus_write; // write to destination low
      28: nextstate = `cpus_write; // write to destination high
      29: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_lhld: LHLD
 
      30: nextstate = `cpus_read; // read high byte
      31: nextstate = `cpus_movrtra; // move read to write address
      32: nextstate = `cpus_read; // read byte low
      33: nextstate = `cpus_read; // read byte high
      34: nextstate = `cpus_lhld; // move to register
      35: nextstate = `cpus_fetchi; // Fetch next instruction
 
      // mac_writedbyte: write double byte
 
      36: nextstate = `cpus_write; // double write
      37: nextstate = `cpus_fetchi; // then fetch
 
      // mac_pop: POP
 
      38: nextstate = `cpus_read; // double it
      39: nextstate = `cpus_pop; // then finish
 
      // mac_xthl: XTHL
 
      40: nextstate = `cpus_read; // double it
      41: nextstate = `cpus_write; // then write
      42: nextstate = `cpus_write; // double it
      43: nextstate = `cpus_movmthl; // place word in hl
 
      // mac_accimm: accumulator immediate
 
      44: nextstate = `cpus_accimm; // finish
 
      // mac_jmp: JMP
 
      45: nextstate = `cpus_read; // double read
      46: nextstate = `cpus_jmp; // then go pc
 
      // mac_call: CALL
 
      47: nextstate = `cpus_read; // double read
      48: nextstate = `cpus_write; // then write
      49: nextstate = `cpus_write; // double write
      50: nextstate = `cpus_jmp; // then go to that
 
      // mac_in: IN
 
      51: nextstate = `cpus_in; // go to IN after getting that
 
      // mac_out: OUT
 
      52: nextstate = `cpus_out; // go to OUT after getting that
 
      // mac_rst: RST
 
      53: nextstate = `cpus_write; // double write
      54: nextstate = `cpus_jmp; // then go to that
 
      default nextstate = 6'bx; // other states never reached
 
   endcase
 
endmodule
 
//
// Alu module
//
// Finds arithmetic operations needed. Latches on the positive edge of the
// clock. There are 8 different types of operations, which come from bits
// 3-5 of the instruction.
//
 
module alu(res, opra, oprb, cin, cout, zout, sout, parity, auxcar, sel);
 
   input  [7:0] opra;   // Input A
   input  [7:0] oprb;   // Input B
   input        cin;    // Carry in
   output       cout;   // Carry out
   output       zout;   // Zero out
   output       sout;   // Sign out
   output       parity; // parity
   output       auxcar; // auxiliary carry
   input  [2:0] sel;    // Operation select
   output [7:0] res;    // Result of alu operation
 
   reg       cout;   // Carry out
   reg       zout;   // Zero out
   reg       sout;   // sign out
   reg       parity; // parity
   reg       auxcar; // auxiliary carry
   reg [7:0] resi;   // Result of alu operation intermediate
   reg [7:0] res;    // Result of alu operation
 
   always @(opra, oprb, cin, sel, res, resi) begin
 
      case (sel)
 
         `aluop_add: begin // add
 
            { cout, resi } = opra+oprb; // find result and carry
//            auxcar = ((opra[3:0]+oprb[3:0]) >> 4) & 1'b1; // find auxiliary carry
//			if ((opra[3:0]+oprb[3:0])>>4) auxcar=1'b1; else auxcar=1'b0;
            auxcar = (((opra[3:0]+oprb[3:0]) >> 4) & 1'b1) ? 1'b1 : 1'b0 ; // find auxiliary carry
 
 
         end
         `aluop_adc: begin // adc
 
            { cout, resi } = opra+oprb+cin; // find result and carry
            auxcar = (((opra[3:0]+oprb[3:0]+cin) >> 4) & 1'b1) ? 1'b1 : 1'b0; // find auxiliary carry
 
         end
         `aluop_sub, `aluop_cmp: begin // sub/cmp
 
            { cout, resi } = opra-oprb; // find result and carry
            auxcar = (((opra[3:0]-oprb[3:0]) >> 4) & 1'b1) ? 1'b1 : 1'b0; // find auxiliary borrow
 
         end
         `aluop_sbb: begin // sbb
 
            { cout, resi } = opra-oprb-cin; // find result and carry
            auxcar = (((opra[3:0]-oprb[3:0]-cin >> 4)) & 1'b1) ? 1'b1 : 1'b0; // find auxiliary borrow 
 
         end
         `aluop_and: begin // ana
 
            { cout, resi } = {1'b0, opra&oprb}; // find result and carry
            auxcar = 1'b0; // clear auxillary carry
 
          end
         `aluop_xor: begin // xra
 
            { cout, resi } = {1'b0, opra^oprb}; // find result and carry
            auxcar = 1'b0; // clear auxillary carry
 
         end
         `aluop_or:  begin // ora
 
            { cout, resi } = {1'b0, opra|oprb}; // find result and carry
            auxcar = 1'b0; // clear auxillary carry
 
         end
 
      endcase
 
      if (sel != `aluop_cmp) res = resi; else res = opra;
      zout <= ~|resi; // set zero flag from result
      sout <= resi[7]; // set sign flag from result
      parity <= ~^resi; // set parity flag from result
 
   end
 
endmodule

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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