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