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

Subversion Repositories cpu8080

[/] [cpu8080/] [trunk/] [project/] [cpu8080.v] - Diff between revs 7 and 9

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 7 Rev 9
Line 14... Line 14...
//     Executes the 8080 instruction set. It is designed to be an internal    //
//     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         //
//     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   //
//     constant with the exception of the data bus. The control signals are   //
//     fully decoded (unlike the orignal 8080), and features read and write   //
//     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       //
//     signals for both memory and I/O space. The I/O space is an 8 bit       //
//     address as in the original 8080.                                       //
//     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 //
//     Like the original 8080, the interrupt vectoring is fully external. The //
//     the external controller forces a full instruction onto the data bus.   //
//     the external controller forces a full instruction onto the data bus.   //
//     The sequence begins with the assertion of interrupt request. The CPU   //
//     The sequence begins with the assertion of interrupt request. The CPU   //
//     will then assert interrupt acknowledge, then it will run a special     //
//     will then assert interrupt acknowledge, then it will run a special     //
//     read cycle with readint asserted for each cycle of a possibly          //
//     read cycle with inta asserted for each cycle of a possibly             //
//     multibyte instruction. This matches the original 8080, which typically //
//     multibyte instruction. This matches the original 8080, which typically //
//     used single byte restart instructions to form a simple interrupt       //
//     used single byte restart instructions to form a simple interrupt       //
//     controller, but was capable of full vectoring via insertion of a jump, //
//     controller, but was capable of full vectoring via insertion of a jump, //
//     call or similar instruction.                                           //
//     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       //
//     The memory, I/O and interrupt fetches all obey a simple clocking       //
//     sequence as follows. The CPU uses the positive clock edge to assert    //
//     sequence as follows. The CPU uses the positive clock edge to assert    //
//     and sample signals and data. The external logic theoretically uses the //
//     and sample signals and data. The external logic theoretically uses the //
//     positive edge to check signal assertions and sample data, but it can   //
//     negative edge to check signal assertions and sample data, but it can   //
//     either use the negative edge, or actually be asynronous logic.         //
//     either use the negative edge, or actually be asynronous logic.         //
 
//     The only caution here is that a read device that samples read signals  //
 
//     from the CPU on a postive edge will present data too late, since read  //
 
//     cycles are only one cycle long. This can be fixed with a wait state.   //
 
//     Negative external clockers may also have an issue with the fact that   //
 
//     the net read time is 1/2 cycle, the negative mid cycle clock to the    //
 
//     next positive clock. Again, and perhaps unfortunately, the fix is to   //
 
//     add an external wait state.                                            //
//                                                                            //
//                                                                            //
//     A standard read sequence is as follows:                                //
//     A standard read sequence is as follows:                                //
//                                                                            //
//                                                                            //
//     1. At the positive clock edge, readmem, readio or readint is asserted. //
//     1. At the positive clock edge, readmem, readio or readint is asserted. //
//     2. At the negative clock edge (or immediately), the external memory    //
//     2. At the negative clock edge (or immediately), the external memory    //
Line 43... Line 58...
//        Signal is deasserted.                                               //
//        Signal is deasserted.                                               //
//                                                                            //
//                                                                            //
//     A standard write sequence is as follows:                               //
//     A standard write sequence is as follows:                               //
//                                                                            //
//                                                                            //
//     1. At the positive edge, data is asserted on the data bus.             //
//     1. At the positive edge, data is asserted on the data bus.             //
//     2. At the postive clock edge, writemem or writeio is asserted.         //
//     2. At the next postive clock edge, writemem or writeio is asserted.    //
//     3. At the next positive clock edge, writemem or writeio is deasserted. //
//     3. At the next positive clock edge, writemem or writeio is deasserted. //
//     4. At the positive edge, the data is deasserted.                       //
//     4. At the next positive edge, the data is deasserted.                  //
//                                                                            //
//                                                                            //
// Dependencies:                                                              //
// Dependencies:                                                              //
//                                                                            //
//                                                                            //
// Revision:                                                                  //
// Revision:                                                                  //
// Revision 0.01 - File Created                                               //
// Revision 0.01 - File Created                                               //
// Additional Comments:                                                       //
// Additional Comments:                                                       //
//                                                                            //
//                                                                            //
// Notes:                                                                     //
 
//                                                                            //
 
// 1. Auxiliary carry is not complete.                                        //
 
//                                                                            //
 
// 2. inta should take place instead of readmem for each interrupt vector     //
 
//    instruction that is fetched. This behavior matches the original Intel   //
 
//    interrupt controller, and it should not be required to gate readmem OFF //
 
//    during interrupt cycles.                                                //
 
//                                                                            //
 
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
 
 
//
//
// CPU states
// CPU states
//
//
Line 201... Line 207...
   reg    [7:0]  rdatahold;   // single byte read data holding
   reg    [7:0]  rdatahold;   // single byte read data holding
   reg    [7:0]  rdatahold2;  // single byte read data holding
   reg    [7:0]  rdatahold2;  // single byte read data holding
   reg    [1:0]  popdes;      // POP destination code
   reg    [1:0]  popdes;      // POP destination code
   reg    [5:0]  statesel;    // state map selector
   reg    [5:0]  statesel;    // state map selector
   reg    [4:0]  nextstate;   // next state output
   reg    [4:0]  nextstate;   // next state output
 
   reg           eienb;       // interrupt enable delay shift reg
 
 
   // Register file. Note that 3'b110 (6) is not used, and is the code for a
   // Register file. Note that 3'b110 (6) is not used, and is the code for a
   // memory reference.
   // memory reference.
 
 
   reg    [7:0]  regfil[0:7];
   reg    [7:0]  regfil[0:7];
Line 215... Line 222...
   reg           auxcar; // auxiliary carry bit
   reg           auxcar; // auxiliary carry bit
   reg           sign; // sign bit
   reg           sign; // sign bit
   reg           zero; // zero bit
   reg           zero; // zero bit
   reg           parity; // parity bit
   reg           parity; // parity bit
   reg           ei; // interrupt enable
   reg           ei; // interrupt enable
 
   reg           intcyc; // in interrupt cycle
 
 
   // ALU communication
   // ALU communication
 
 
   wire   [7:0]  alures;  // result
   wire   [7:0]  alures;  // result
   reg    [7:0]  aluopra; // left side operand
   reg    [7:0]  aluopra; // left side operand
Line 243... Line 251...
      readmem <= 0; // all signals out false
      readmem <= 0; // all signals out false
      writemem <= 0;
      writemem <= 0;
      readio <= 0;
      readio <= 0;
      writeio <= 0;
      writeio <= 0;
      inta <= 0;
      inta <= 0;
      ei <= 1; // interrupts on on reset, check this
      intcyc <= 0;
 
      ei <= 1;
 
      eienb <= 0;
 
 
   end else case (state)
   end else case (state)
 
 
      `cpus_fetchi: begin // start of instruction fetch
      `cpus_fetchi: begin // start of instruction fetch
 
 
         // interrupt is like a normal instruction cycle, except we set the 
         // if interrupt request is on, enter interrupt cycle, else exit it now
         // acknowledge for the entire instruction fetch.
         if (intr&&ei) begin
         if (intr && ei) inta <= 1; // interrupt request, set interrupt acknowledge
 
         else inta <= 0; // clear interrupt acknowledge
            intcyc <= 1; // enter interrupt cycle
         addr <= pc; // place current program count on output
            inta <= 1; // activate interrupt acknowledge
 
            ei <= 0; // disable interrupts
 
 
 
         end else begin
 
 
 
            intcyc <= 0; // leave interrupt cycle
         readmem <= 1; // activate instruction memory read
         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
         state <= `cpus_fetchi2; // next state
 
 
      end
      end
 
 
      `cpus_fetchi2: begin // complete instruction memory read
      `cpus_fetchi2: begin // complete instruction memory read
 
 
         readmem <= 0; // Deactivate instruction memory read
         readmem <= 0; // Deactivate instruction memory read
 
         inta <= 0; // and interrupt acknowledge
 
 
         // We split off the instructions into 4 groups. Most of the 8080
         // We split off the instructions into 4 groups. Most of the 8080
         // instructions are in the MOV and ACC operations class.
         // instructions are in the MOV and ACC operations class.
 
 
         case (data[7:6]) // Decode top level
         case (data[7:6]) // Decode top level
Line 840... Line 862...
 
 
                  6'b001101: begin // CALL
                  6'b001101: begin // CALL
 
 
                     raddrhold <= pc+1; // pick up call address
                     raddrhold <= pc+1; // pick up call address
                     waddrhold <= sp-2; // place address on stack
                     waddrhold <= sp-2; // place address on stack
                     { wdatahold2, wdatahold } <= pc+3; // of address after call
                     // if interrupt cycle, use current pc, else use address
 
                     // after call
 
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
 
                     else { wdatahold2, wdatahold } <= pc+3;
                     sp <= sp-2; // pushdown stack
                     sp <= sp-2; // pushdown stack
                     statesel <= `mac_call; // finish CALL
                     statesel <= `mac_call; // finish CALL
                     state <= `cpus_read;
                     state <= `cpus_read;
 
 
                  end
                  end
Line 925... Line 950...
                  6'b000111, 6'b001111, 6'b010111, 6'b011111, 6'b100111,
                  6'b000111, 6'b001111, 6'b010111, 6'b011111, 6'b100111,
                  6'b101111, 6'b110111, 6'b111111: begin // RST
                  6'b101111, 6'b110111, 6'b111111: begin // RST
 
 
                     pc <= data & 8'b00111000; // place restart value in PC
                     pc <= data & 8'b00111000; // place restart value in PC
                     waddrhold <= sp-2; // place address on stack
                     waddrhold <= sp-2; // place address on stack
 
                     // if interrupt cycle, use current pc, else use address
 
                     // after call
 
                     if (intcyc) { wdatahold2, wdatahold } <= pc;
 
                     else { wdatahold2, wdatahold } <= pc+3;
                     { wdatahold2, wdatahold } <= pc+1; // of address after call
                     { wdatahold2, wdatahold } <= pc+1; // of address after call
                     sp <= sp-2; // pushdown stack
                     sp <= sp-2; // pushdown stack
                     statesel <= `mac_writedbyte; // finish RST
                     statesel <= `mac_writedbyte; // finish RST
                     state <= `cpus_write; // write to stack
                     state <= `cpus_write; // write to stack
 
 
Line 1038... Line 1067...
 
 
      `cpus_read: begin
      `cpus_read: begin
 
 
         addr <= raddrhold; // place address on output
         addr <= raddrhold; // place address on output
         raddrhold <= raddrhold+1; // next address
         raddrhold <= raddrhold+1; // next address
         readmem <= 1; // activate instruction memory read
         if (intcyc) inta <= 1; // activate interrupt acknowledge
 
         else readmem <= 1; // activate instruction memory read
         state <= `cpus_read2; // next state
         state <= `cpus_read2; // next state
 
 
      end
      end
 
 
      `cpus_read2: begin // continue read #2
      `cpus_read2: begin // continue read #2
Line 1050... Line 1080...
         if (!waitr) begin // no wait selected, otherwise cycle
         if (!waitr) begin // no wait selected, otherwise cycle
 
 
            rdatahold2 <= rdatahold; // shift data
            rdatahold2 <= rdatahold; // shift data
            rdatahold <= data; // read new data
            rdatahold <= data; // read new data
            readmem <= 0; // deactivate instruction memory read
            readmem <= 0; // deactivate instruction memory read
 
            inta <= 0; // deactivate interrupt acknowledge
            state <= nextstate; // get next macro state
            state <= nextstate; // get next macro state
            statesel <= statesel+1; // and index next in macro 
            statesel <= statesel+1; // and index next in macro 
 
 
         end
         end
 
 
Line 1138... Line 1169...
 
 
      end
      end
 
 
      `cpus_halt: begin // Halt waiting for interrupt
      `cpus_halt: begin // Halt waiting for interrupt
 
 
         // nothing to do, we leave the state at halt, which will cause it to
         // If there is an interrupt request and interrupts are enabled, then we
         // be executed continually until we exit.
         // can leave halt. Otherwise we stay here.
 
         if (intr&&ei) state <= `cpus_fetchi; // Fetch next instruction
 
         else state <= `cpus_halt;
 
 
 
 
      end
      end
 
 
      `cpus_movtr: begin // move to register
      `cpus_movtr: begin // move to register
 
 

powered by: WebSVN 2.1.0

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