From b4be27e0019577d7f466300b1d15ba961caa4aae Mon Sep 17 00:00:00 2001 From: MicroCoreLabs Date: Sun, 21 Aug 2022 20:37:47 -0700 Subject: [PATCH] Uploaded_8_21_2022 --- MCL86/Core/Test/eu.v | 573 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 573 insertions(+) create mode 100644 MCL86/Core/Test/eu.v diff --git a/MCL86/Core/Test/eu.v b/MCL86/Core/Test/eu.v new file mode 100644 index 0000000..2e179b4 --- /dev/null +++ b/MCL86/Core/Test/eu.v @@ -0,0 +1,573 @@ +// +// +// File Name : mcl86_eu_core.v +// Used on : +// Author : Ted Fried, MicroCore Labs +// Creation : 10/8/2015 +// Code Type : Synthesizable +// +// Description: +// ============ +// +// Execution Unit of the i8088 processor - Microsequencer +// +//------------------------------------------------------------------------ +// +// Modification History: +// ===================== +// +// Revision 1.0 10/8/15 +// Initial revision +// +// +//------------------------------------------------------------------------ +// +// Copyright (c) 2020 Ted Fried +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//------------------------------------------------------------------------ + + +module mcl86_eu_core + ( + input CORE_CLK_INT, // Core Clock + input RESET_INT, // Pipelined 8088 RESET pin + input TEST_N_INT, // Pipelined 8088 TEST_n pin + + + output [15:0] EU_BIU_COMMAND, // EU to BIU Signals + output [15:0] EU_BIU_DATAOUT, + output [15:0] EU_REGISTER_R3, + output EU_PREFIX_LOCK, + output EU_FLAG_I, + + + input BIU_DONE, // BIU to EU Signals + input BIU_CLK_COUNTER_ZERO, + input BIU_NMI_CAUGHT, + output BIU_NMI_DEBOUNCE, + input BIU_INTR, + + + input [7:0] PFQ_TOP_BYTE, + input PFQ_EMPTY, + input[15:0] PFQ_ADDR_OUT, + + + input [15:0] BIU_REGISTER_ES, + input [15:0] BIU_REGISTER_SS, + input [15:0] BIU_REGISTER_CS, + input [15:0] BIU_REGISTER_DS, + input [15:0] BIU_REGISTER_RM, + input [15:0] BIU_REGISTER_REG, + input [15:0] BIU_RETURN_DATA + + ); + +//------------------------------------------------------------------------ + + +// Internal Signals + +reg eu_add_carry; +reg eu_add_carry8; +reg eu_add_aux_carry; +reg eu_add_overflow16; +reg eu_add_overflow8; +reg eu_stall_pipeline; +reg eu_flag_t_d; +reg biu_done_d1; +reg biu_done_d2; +reg eu_tr_latched; +reg biu_done_caught; +reg eu_biu_req_d1; +reg intr_enable_delayed; +wire eu_prefix_rep; +wire eu_prefix_repnz; +wire eu_tf_debounce; +wire eu_prefix_lock ; +wire eu_biu_req; +wire eu_parity; +wire eu_flag_o; +wire eu_flag_d; +wire eu_flag_i; +wire eu_flag_t; +wire eu_flag_s; +wire eu_flag_z; +wire eu_flag_a; +wire eu_flag_p; +wire eu_flag_c; +wire eu_opcode_jump_call; +wire intr_asserted; +wire eu_jump_boolean; +reg [12:0] eu_rom_address; +reg [51:0] eu_calling_address; +reg [15:0] eu_register_ax; +reg [15:0] eu_register_bx; +reg [15:0] eu_register_cx; +reg [15:0] eu_register_dx; +reg [15:0] eu_register_sp; +reg [15:0] eu_register_bp; +reg [15:0] eu_register_si; +reg [15:0] eu_register_di; +reg [15:0] eu_flags; +reg [15:0] eu_register_r0; +reg [15:0] eu_register_r1; +reg [15:0] eu_register_r2; +reg [15:0] eu_register_r3; +reg [15:0] eu_biu_command; +reg [15:0] eu_biu_dataout; +reg [15:0] eu_alu_last_result; +wire [15:0] adder_out; +wire [16:0] carry; +wire [2:0] eu_opcode_type; +wire [3:0] eu_opcode_dst_sel; +wire [3:0] eu_opcode_op0_sel; +wire [3:0] eu_opcode_op1_sel; +wire [15:0] eu_opcode_immediate; +wire [2:0] eu_opcode_jump_src; +wire [3:0] eu_opcode_jump_cond; +wire [15:0] system_signals; +wire [15:0] eu_alu2; +wire [15:0] eu_alu3; +wire [15:0] eu_alu4; +wire [15:0] eu_alu5; +wire [15:0] eu_alu6; +wire [15:0] eu_alu7; +wire [15:0] eu_alu_out; +wire [15:0] eu_operand0; +wire [15:0] eu_operand1; +wire [31:0] eu_rom_data; + +wire [15:0] adc_total; +wire [15:0] sbb_total; +reg eu_overflow_fix; +reg eu_add_overflow8_fixed; +reg eu_add_overflow16_fixed; + + +//------------------------------------------------------------------------ +// +// EU Microcode RAM. 4Kx32 DPRAM +// +//------------------------------------------------------------------------ + +eu_rom EU_4Kx32 ( + + .clka (CORE_CLK_INT), + .addra (eu_rom_address[11:0]), + .douta (eu_rom_data) + + ); + + + +//------------------------------------------------------------------------ +// +// Combinationals +// +//------------------------------------------------------------------------ + +assign EU_BIU_COMMAND = eu_biu_command; +assign EU_BIU_DATAOUT = eu_biu_dataout; +assign EU_REGISTER_R3 = eu_register_r3; +assign EU_FLAG_I = intr_enable_delayed; +assign EU_PREFIX_LOCK = eu_prefix_lock; + + +// EU ROM opcode decoder +assign eu_opcode_type = eu_rom_data[30:28]; +assign eu_opcode_dst_sel = eu_rom_data[27:24]; +assign eu_opcode_op0_sel = eu_rom_data[23:20]; +assign eu_opcode_op1_sel = eu_rom_data[19:16]; +assign eu_opcode_immediate = eu_rom_data[15:0]; + +assign eu_opcode_jump_call = eu_rom_data[24]; +assign eu_opcode_jump_src = eu_rom_data[22:20]; +assign eu_opcode_jump_cond = eu_rom_data[19:16]; + + + +assign eu_operand0 = (eu_opcode_op0_sel==4'h0) ? eu_register_ax : + (eu_opcode_op0_sel==4'h1) ? eu_register_bx : + (eu_opcode_op0_sel==4'h2) ? eu_register_cx : + (eu_opcode_op0_sel==4'h3) ? eu_register_dx : + (eu_opcode_op0_sel==4'h4) ? eu_register_sp : + (eu_opcode_op0_sel==4'h5) ? eu_register_bp : + (eu_opcode_op0_sel==4'h6) ? eu_register_si : + (eu_opcode_op0_sel==4'h7) ? eu_register_di : + (eu_opcode_op0_sel==4'h8) ? eu_flags : + (eu_opcode_op0_sel==4'h9) ? eu_register_r0 : + (eu_opcode_op0_sel==4'hA) ? eu_register_r1 : + (eu_opcode_op0_sel==4'hB) ? eu_register_r2 : + (eu_opcode_op0_sel==4'hC) ? eu_register_r3 : + (eu_opcode_op0_sel==4'hD) ? eu_biu_command : + (eu_opcode_op0_sel==4'hE) ? system_signals : + 16'h0 ; + + +assign eu_operand1 = (eu_opcode_op1_sel==4'h0) ? BIU_REGISTER_ES : + (eu_opcode_op1_sel==4'h1) ? BIU_REGISTER_SS : + (eu_opcode_op1_sel==4'h2) ? BIU_REGISTER_CS : + (eu_opcode_op1_sel==4'h3) ? BIU_REGISTER_DS : + (eu_opcode_op1_sel==4'h4) ? { 8'h00 , PFQ_TOP_BYTE } : + (eu_opcode_op1_sel==4'h5) ? BIU_REGISTER_RM : + (eu_opcode_op1_sel==4'h6) ? BIU_REGISTER_REG : + (eu_opcode_op1_sel==4'h7) ? BIU_RETURN_DATA : + (eu_opcode_op1_sel==4'h8) ? PFQ_ADDR_OUT : + (eu_opcode_op1_sel==4'h9) ? eu_register_r0 : + (eu_opcode_op1_sel==4'hA) ? eu_register_r1 : + (eu_opcode_op1_sel==4'hB) ? eu_register_r2 : + (eu_opcode_op1_sel==4'hC) ? eu_register_r3 : + (eu_opcode_op1_sel==4'hD) ? eu_alu_last_result : + (eu_opcode_op1_sel==4'hE) ? system_signals : + eu_opcode_immediate ; + + + +// JUMP condition codes +assign eu_jump_boolean = (eu_opcode_jump_cond==4'h0) ? 1'b1 : // unconditional jump + (eu_opcode_jump_cond==4'h1 && eu_alu_last_result!=16'h0) ? 1'b1 : + (eu_opcode_jump_cond==4'h2 && eu_alu_last_result==16'h0) ? 1'b1 : + 1'b0 ; + + + +// Consolidated system signals +assign system_signals[13] = eu_add_carry8; +assign system_signals[12] = BIU_CLK_COUNTER_ZERO; +assign system_signals[11] = eu_add_overflow16; +assign system_signals[9] = eu_add_overflow8; +assign system_signals[8] = eu_tr_latched; +assign system_signals[7] = ~PFQ_EMPTY; +assign system_signals[6] = biu_done_caught; +assign system_signals[5] = TEST_N_INT; +assign system_signals[4] = eu_add_aux_carry; +assign system_signals[3] = BIU_NMI_CAUGHT; +assign system_signals[2] = eu_parity; +assign system_signals[1] = intr_asserted; +assign system_signals[0] = eu_add_carry; + + +assign eu_prefix_repnz = eu_flags[15]; +assign eu_prefix_rep = eu_flags[14]; +assign eu_prefix_lock = eu_flags[13]; +assign BIU_NMI_DEBOUNCE = eu_flags[12]; +assign eu_flag_o = eu_flags[11]; +assign eu_flag_d = eu_flags[10]; +assign eu_flag_i = eu_flags[9]; +assign eu_flag_t = eu_flags[8]; +assign eu_flag_s = eu_flags[7]; +assign eu_flag_z = eu_flags[6]; +assign eu_tf_debounce = eu_flags[5]; +assign eu_flag_a = eu_flags[4]; +assign eu_nmi_pending = eu_flags[3]; +assign eu_flag_p = eu_flags[2]; +assign eu_flag_temp = eu_flags[1]; +assign eu_flag_c = eu_flags[0]; + + + +// EU ALU Operations +// ------------------------------------------ +// eu_alu0 = NOP +// eu_alu1 = JUMP +assign eu_alu2 = adder_out; // ADD +assign eu_alu3 = { eu_operand0[7:0] , eu_operand0[15:8] }; // BYTESWAP +assign eu_alu4 = eu_operand0 & eu_operand1; // AND +assign eu_alu5 = eu_operand0 | eu_operand1; // OR +assign eu_alu6 = eu_operand0 ^ eu_operand1; // XOR +assign eu_alu7 = { 1'b0 , eu_operand0[15:1] }; // SHR + + + + +// Mux the ALU operations +assign eu_alu_out = (eu_opcode_type==3'h2) ? eu_alu2 : + (eu_opcode_type==3'h3) ? eu_alu3 : + (eu_opcode_type==3'h4) ? eu_alu4 : + (eu_opcode_type==3'h5) ? eu_alu5 : + (eu_opcode_type==3'h6) ? eu_alu6 : + (eu_opcode_type==3'h7) ? eu_alu7 : + 20'hEEEEE; + + + + + +// Generate 16-bit full adder for the EU +assign carry[0] = 1'b0; +genvar i; +generate + for (i=0; i < 16; i=i+1) + begin : GEN_ADDER + assign adder_out[i] = eu_operand0[i] ^ eu_operand1[i] ^ carry[i]; + assign carry[i+1] = (eu_operand0[i] & eu_operand1[i]) | (eu_operand0[i] & carry[i]) | (eu_operand1[i] & carry[i]); + end +endgenerate + +assign eu_parity = ~(eu_alu_last_result[0]^eu_alu_last_result[1]^eu_alu_last_result[2]^eu_alu_last_result[3]^eu_alu_last_result[4]^eu_alu_last_result[5]^eu_alu_last_result[6]^eu_alu_last_result[7]); + + +assign eu_biu_req = eu_biu_command[9]; + +assign intr_asserted = BIU_INTR & intr_enable_delayed; + + +assign new_instruction = (eu_rom_address[12:8]==5'h01) ? 1'b1 : 1'b0; + + +assign adc_total = eu_register_r0 + eu_register_r1 + eu_flag_c; +assign sbb_total = eu_register_r0 - eu_register_r1 - eu_flag_c; + + +//------------------------------------------------------------------------------------------ +// +// EU Microsequencer +// +//------------------------------------------------------------------------------------------ + +always @(posedge CORE_CLK_INT) +begin : EU_MICROSEQUENCER + + if (RESET_INT==1'b1) + begin + biu_done_d1 <= 'h0; + biu_done_d2 <= 'h0; + eu_biu_req_d1 <= 'h0; + biu_done_caught <= 'h0; + eu_flag_t_d <= 'h0; + eu_tr_latched <= 'h0; + eu_add_carry <= 'h0; + eu_add_carry8 <= 'h0; + eu_add_aux_carry <= 'h0; + eu_add_overflow16 <= 'h0; + eu_add_overflow8 <= 'h0; + eu_alu_last_result <= 'h0; + eu_register_ax <= 'h0; + eu_register_bx <= 'h0; + eu_register_cx <= 'h0; + eu_register_dx <= 'h0; + eu_register_sp <= 'h0; + eu_register_bp <= 'h0; + eu_register_si <= 'h0; + eu_register_di <= 'h0; + eu_flags <= 'h0; + eu_register_r0 <= 'h0; + eu_register_r1 <= 'h0; + eu_register_r2 <= 'h0; + eu_register_r3 <= 'h0; + eu_biu_command <= 'h0; + eu_biu_dataout <= 'h0; + eu_stall_pipeline <= 'h0; + eu_rom_address <= 13'h0020; + eu_calling_address <= 'h0; + intr_enable_delayed <= 1'b0; + end + +else + begin + + // Delay the INTR enable flag until after the next instruction begins. + // No delay when it is disabled. + if (eu_flag_i==1'b0) + begin + intr_enable_delayed <= 1'b0; + end + else + if (new_instruction==1'b1) + begin + intr_enable_delayed <= eu_flag_i; + end + + // Latch the TF flag on its rising edge. + eu_flag_t_d <= eu_flag_t; + if (eu_flag_t_d==1'b0 && eu_flag_t==1'b1) + begin + eu_tr_latched <= 1'b1; + end + else if (eu_tf_debounce==1'b1) + begin + eu_tr_latched <= 1'b0; + end + + + + // Latch the done bit from the biu. + // Debounce it when the request is released. + biu_done_d1 <= BIU_DONE; + biu_done_d2 <= biu_done_d1; + eu_biu_req_d1 <= eu_biu_req; + if (biu_done_d2==1'b0 && biu_done_d1==1'b1) + biu_done_caught <= 1'b1; + else if (eu_biu_req_d1==1'b1 && eu_biu_req==1'b0) + biu_done_caught <= 1'b0; + + +// ADC - Byte +// +if (eu_rom_address == 16'h0A03) + begin + eu_overflow_fix <= 1'b1; + + if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b0) && (adc_total[7]==1'b1) ) || + ( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b1) && (adc_total[7]==1'b0) ) ) + begin + eu_add_overflow8_fixed <= 1'b1; + end + else + begin + eu_add_overflow8_fixed <= 1'b0; + end + end + + +// SBB - Byte +// +if (eu_rom_address == 16'h0AAE) + begin + eu_overflow_fix <= 1'b1; + + if ( ( (eu_register_r0[7]==1'b0) && (eu_register_r1[7]==1'b1) && (sbb_total[7]==1'b1) ) || + ( (eu_register_r0[7]==1'b1) && (eu_register_r1[7]==1'b0) && (sbb_total[7]==1'b0) ) ) + begin + eu_add_overflow8_fixed <= 1'b1; + end + else + begin + eu_add_overflow8_fixed <= 1'b0; + end + end + +// ADC - Word +// +if (eu_rom_address == 16'h0A12) + begin + eu_overflow_fix <= 1'b1; + + if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b0) && (adc_total[15]==1'b1) ) || + ( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b1) && (adc_total[15]==1'b0) ) ) + begin + eu_add_overflow16_fixed <= 1'b1; + end + else + begin + eu_add_overflow16_fixed <= 1'b0; + end + end + + +// SBB - Word +// +if (eu_rom_address == 16'h0ABA) + begin + eu_overflow_fix <= 1'b1; + + if ( ( (eu_register_r0[15]==1'b0) && (eu_register_r1[15]==1'b1) && (sbb_total[15]==1'b1) ) || + ( (eu_register_r0[15]==1'b1) && (eu_register_r1[15]==1'b0) && (sbb_total[15]==1'b0) ) ) + begin + eu_add_overflow16_fixed <= 1'b1; + end + else + begin + eu_add_overflow16_fixed <= 1'b0; + end + end + +if (eu_rom_address == 16'h0011) eu_overflow_fix <= 1'b0; + + + // Generate and store flags for addition + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h2) + begin + eu_add_carry <= carry[16]; + eu_add_carry8 <= carry[8]; + eu_add_aux_carry <= carry[4]; + eu_add_overflow16 <= (eu_overflow_fix==1'b1) ? eu_add_overflow16_fixed : (carry[16] ^ carry[15]); + eu_add_overflow8 <= (eu_overflow_fix==1'b1) ? eu_add_overflow8_fixed : (carry[8] ^ carry[7]); + end + + + // Register writeback + if (eu_stall_pipeline==1'b0 && eu_opcode_type!=3'h0 && eu_opcode_type!=3'h1) + begin + eu_alu_last_result <= eu_alu_out[15:0]; + case (eu_opcode_dst_sel) // synthesis parallel_case + 4'h0 : eu_register_ax <= eu_alu_out[15:0]; + 4'h1 : eu_register_bx <= eu_alu_out[15:0]; + 4'h2 : eu_register_cx <= eu_alu_out[15:0]; + 4'h3 : eu_register_dx <= eu_alu_out[15:0]; + 4'h4 : eu_register_sp <= eu_alu_out[15:0]; + 4'h5 : eu_register_bp <= eu_alu_out[15:0]; + 4'h6 : eu_register_si <= eu_alu_out[15:0]; + 4'h7 : eu_register_di <= eu_alu_out[15:0]; + 4'h8 : eu_flags <= eu_alu_out[15:0]; + 4'h9 : eu_register_r0 <= eu_alu_out[15:0]; + 4'hA : eu_register_r1 <= eu_alu_out[15:0]; + 4'hB : eu_register_r2 <= eu_alu_out[15:0]; + 4'hC : eu_register_r3 <= eu_alu_out[15:0]; + 4'hD : eu_biu_command <= eu_alu_out[15:0]; + //4'hE : ; + 4'hF : eu_biu_dataout <= eu_alu_out[15:0]; + default : ; + endcase + end + + + // JUMP Opcode + if (eu_stall_pipeline==1'b0 && eu_opcode_type==3'h1 && eu_jump_boolean==1'b1) + begin + eu_stall_pipeline <= 1'b1; + + // For subroutine CALLs, store next opcode address + if (eu_opcode_jump_call==1'b1) + begin + eu_calling_address[51:0] <= {eu_calling_address[38:0] , eu_rom_address[12:0] }; // 4 deep calling addresses + end + + case (eu_opcode_jump_src) // synthesis parallel_case + 3'h0 : eu_rom_address <= eu_opcode_immediate[12:0]; + 3'h1 : eu_rom_address <= { 4'b0 , 1'b1 , PFQ_TOP_BYTE }; // If only used for primary opcode jump, maybe make fixed prepend rather than immediate value prepend? + 3'h2 : eu_rom_address <= { eu_opcode_immediate[4:0], PFQ_TOP_BYTE[7:6] , PFQ_TOP_BYTE[2:0] , 3'b000 }; // Rearranged mod_reg_rm byte - imm,MOD,RM,000 + 3'h3 : begin + eu_rom_address <= eu_calling_address[12:0]; + eu_calling_address[38:0] <= eu_calling_address[51:13]; + end + 3'h4 : eu_rom_address <= { eu_opcode_immediate[7:0], eu_biu_dataout[3:0] , 1'b0 }; // Jump table for EA register fetch decoding. Jump Addresses decoded from biu_dataout. + 3'h5 : eu_rom_address <= { eu_opcode_immediate[6:0], eu_biu_dataout[3:0] , 2'b00 }; // Jump table for EA register writeback decoding. Jump Addresses decoded from biu_dataout. + 3'h6 : eu_rom_address <= { eu_opcode_immediate[12:3], eu_biu_dataout[5:3] }; // Jump table for instructions that share same opcode and decode using the REG field. + + default : ; + endcase + end + + else + begin + eu_stall_pipeline <= 1'b0; // Debounce the pipeline stall + eu_rom_address <= eu_rom_address + 1'b1; + end + +end +end // EU Microsequencer + + + + +endmodule // eu.v