diff --git a/rtl/cpu/alu.sv b/rtl/cpu/alu.sv index 28dfaae..78c8742 100644 --- a/rtl/cpu/alu.sv +++ b/rtl/cpu/alu.sv @@ -9,6 +9,7 @@ module alu ( input logic alu_op_valid_i, input alu_op_t alu_op_i, input logic [7:0] operand_i, + input logic [2:0] inx8_i, // Only used for bit/set/res input alu16_op_t alu16_op_i, input logic [15:0] inx16_i, @@ -31,6 +32,9 @@ module alu ( logic [ 7:0] a_xor; logic [ 7:0] f_xor; + logic [ 7:0] a_bit; // Never written, only to test + logic [ 7:0] f_bit; + logic [16:0] out16_add; logic [ 7:0] f16_add; logic [15:0] out16_inc; @@ -41,15 +45,19 @@ module alu ( assign a_we = alu_op_valid_i; assign a_next = (alu_op_i == ALU_OP_XOR) ? a_xor : - a_xor; + a_r; assign f_we = alu_op_valid_i; assign f_next = (alu_op_i == ALU_OP_XOR) ? f_xor : - f_xor; + (alu_op_i == ALU_OP_BIT) ? f_bit : + f_r; assign a_xor = (a_r ^ operand_i); assign f_xor = {~(|a_xor), 3'b0, f_r[3:0]}; + assign a_bit = (operand_i - {4'b0, inx8_i}); + assign f_bit = {~(|a_bit), 2'b10, f_r[4:0]}; + assign out16_dec = (inx16_i - 16'h01); assign a_o = a_r; diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv index 7bbe8f0..39e7abf 100644 --- a/rtl/cpu/control.sv +++ b/rtl/cpu/control.sv @@ -22,6 +22,7 @@ module control ( output alu_op_t alu_op_o, output op_src_t op_src_o, output op_dest_t op_dest_o, + output reg8_t reg8_src_o, output alu16_op_t alu16_op_o, output reg16_t reg16_src_o, output reg16_t reg16_dest_o, @@ -112,8 +113,9 @@ module control ( ST1_DEC: state_next = decoder_need_instr1 ? ST2_DEC : ST2_EXEC; ST2_EXEC: state_next = ST0_ADDR; - ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST0_ADDR; + ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST3_EXEC; ST3_DEC: state_next = ST4_EXEC; + ST3_EXEC: state_next = ST0_ADDR; ST4_EXEC: state_next = ST0_ADDR; endcase end @@ -136,6 +138,8 @@ module control ( .op_src_o (op_src_o), .op_dest_o (op_dest_o), + .reg8_src_o (reg8_src_o), + .alu16_op_o (alu16_op_o), .reg16_src_o (reg16_src_o), .reg16_dest_o (reg16_dest_o), @@ -148,8 +152,8 @@ module control ( assign decoder_instr1_selected = (state_r == ST2_DEC) ? rdata_i : operand0_r; assign decoder_instr2_selected = (state_r == ST3_DEC) ? rdata_i : operand1_r; - assign is_undef = (state_r != ST0_ADDR & decoder_is_undef); - assign instr_valid = (state_r == ST2_EXEC | state_r == ST4_EXEC); + assign is_undef = instr_valid & decoder_is_undef; + assign instr_valid = (state_r == ST2_EXEC | state_r == ST3_EXEC | state_r == ST4_EXEC); assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2); @@ -163,8 +167,8 @@ module control ( assign operand8_o = operand0_r; assign operand16_o = {operand1_r, operand0_r}; - assign memory_we_o = ((state_r == ST2_EXEC) | (state_r == ST4_EXEC)) & decoder_memory_we; - assign adr_src_o = (state_r == ST2_EXEC) | (state_r == ST4_EXEC) ? decoder_adr_src : - ADR_SRC_PC; + assign memory_we_o = instr_valid & decoder_memory_we; + assign adr_src_o = instr_valid ? decoder_adr_src : + ADR_SRC_PC; endmodule : control diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv index ed2c11c..fe1475a 100644 --- a/rtl/cpu/cpu.sv +++ b/rtl/cpu/cpu.sv @@ -65,6 +65,7 @@ module cpu ( .instr_undef_o (instr_undef), .operand8_o (operand8), .operand16_o (operand16), + .reg8_src_o (reg8_rselect), .alu16_op_o (alu16_op), .reg16_src_o (reg16_rselect), .reg16_dest_o (reg16_wselect), @@ -78,6 +79,7 @@ module cpu ( .alu_op_valid_i(alu_op_valid), .alu_op_i (alu_op), .operand_i (alu_operand), + .inx8_i (operand8[5:3]), // Used for bit/set/res .a_o (rega), .f_o (regf), .alu16_op_i (alu16_op), @@ -105,15 +107,16 @@ module cpu ( .hl_o (hl) ); - assign alu_operand = (op_src == OP_SRC_A) ? rega : - '0; + assign alu_operand = (op_src == OP_SRC_A) ? rega : + (op_src == OP_SRC_OPERAND8) ? operand8 : + (op_src == OP_SRC_REG8) ? reg8_rdata : + '0; assign reg8_wselect = reg8_t'('X); assign reg8_we = '0; assign reg8_wdata = operand8; assign reg16_we = instr_valid & (op_dest == OP_DEST_REG16); assign reg16_wdata = (op_src == OP_SRC_OPERAND16) ? operand16 : alu_out16; - assign reg8_rselect = reg8_t'('X); assign reg16_rselect2 = reg16_wselect; assign address_o = (adr_src == ADR_SRC_HL) ? hl : diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh index 0baa93d..1c69c23 100644 --- a/rtl/cpu/cpu_pkg.svh +++ b/rtl/cpu/cpu_pkg.svh @@ -10,6 +10,7 @@ package cpu_pkg; ST2_EXEC, ST2_DEC, ST3_DEC, + ST3_EXEC, ST4_EXEC } state_t; @@ -19,7 +20,9 @@ package cpu_pkg; REG8_D = 3'h02, REG8_E = 3'h03, REG8_H = 3'h04, - REG8_L = 3'h05 + REG8_L = 3'h05, + REG8_PHL = 3'h06, + REG8_A = 3'h07 } reg8_t; typedef enum logic [1:0] { @@ -29,15 +32,16 @@ package cpu_pkg; REG16_SP_AF = 2'h03 } reg16_t; - typedef enum logic [2:0] { - ALU_OP_ADD = 3'h00, - ALU_OP_ADC = 3'h01, - ALU_OP_SUB = 3'h02, - ALU_OP_SBC = 3'h03, - ALU_OP_AND = 3'h04, - ALU_OP_XOR = 3'h05, - ALU_OP_OR = 3'h06, - ALU_OP_CP = 3'h07 + typedef enum logic [3:0] { + ALU_OP_ADD = 4'h00, + ALU_OP_ADC = 4'h01, + ALU_OP_SUB = 4'h02, + ALU_OP_SBC = 4'h03, + ALU_OP_AND = 4'h04, + ALU_OP_XOR = 4'h05, + ALU_OP_OR = 4'h06, + ALU_OP_CP = 4'h07, + ALU_OP_BIT = 4'h08 } alu_op_t; typedef enum logic [1:0] { @@ -49,12 +53,13 @@ package cpu_pkg; typedef enum { OP_SRC_A, OP_SRC_REG8, + OP_SRC_OPERAND8, OP_SRC_OPERAND16, OP_SRC_REG16 } op_src_t; typedef enum { - OP_DEST_A, + OP_DEST_REG8, OP_DEST_REG16 } op_dest_t; diff --git a/rtl/cpu/decode.sv b/rtl/cpu/decode.sv index 83cc89d..6fb9b75 100644 --- a/rtl/cpu/decode.sv +++ b/rtl/cpu/decode.sv @@ -21,6 +21,7 @@ module decode ( output op_src_t op_src_o, output op_dest_t op_dest_o, + output reg8_t reg8_src_o, output alu16_op_t alu16_op_o, output reg16_t reg16_dest_o, output reg16_t reg16_src_o, @@ -35,10 +36,12 @@ module decode ( logic [1:0] dec_p; logic dec_q; + logic is_cb; logic is_ld_rr_nnnn; logic is_ld_sp_nnnn; logic is_ldd_hl_a; logic is_alu_a_r; + logic is_bit_n_r; reg8_t reg8_src; @@ -48,21 +51,30 @@ module decode ( assign dec_p = instr0_i[5:4]; assign dec_q = instr0_i[3]; + assign is_cb = (instr0_i == 8'hCB); + assign is_ld_rr_nnnn = (dec_x == 2'h0) & (dec_z == 3'h1) & ~dec_q & (dec_p != 2'h3); assign is_ld_sp_nnnn = (dec_x == 2'h0) & (dec_z == 3'h1) & ~dec_q & (dec_p == 2'h3); assign is_ldd_hl_a = (dec_x == 2'h0) & (dec_z == 3'h2) & ~dec_q & (dec_p == 2'h3); assign is_alu_a_r = (dec_x == 3'h2); + assign is_bit_n_r = (is_cb & instr1_i[7:6] == 2'h1); - assign need_instr1_o = is_ld_sp_nnnn | is_ld_rr_nnnn; + + assign reg8_src = is_cb ? reg8_t'(instr1_i[2:0]) : + reg8_t'(dec_z); + + + assign need_instr1_o = is_ld_sp_nnnn | is_ld_rr_nnnn | is_cb; assign need_instr2_o = is_ld_sp_nnnn | is_ld_rr_nnnn; - assign undef_o = ~(is_ld_sp_nnnn | is_ld_rr_nnnn | is_alu_a_r | is_ldd_hl_a); + assign undef_o = ~(is_ld_sp_nnnn | is_ld_rr_nnnn | is_alu_a_r | is_ldd_hl_a | is_bit_n_r); assign sp_we_o = is_ld_sp_nnnn & (state_i == ST4_EXEC); - assign alu_op_o = alu_op_t'(dec_y); - assign alu_op_valid_o = is_alu_a_r; + assign alu_op_valid_o = is_alu_a_r | is_bit_n_r; + assign alu_op_o = is_bit_n_r ? ALU_OP_BIT : + alu_op_t'({1'b0, dec_y}); assign op_dest_o = is_ld_rr_nnnn ? OP_DEST_REG16 : is_ldd_hl_a ? OP_DEST_REG16 : @@ -72,6 +84,7 @@ module decode ( (is_alu_a_r & reg8_src != REG8_A) ? OP_SRC_REG8 : is_ld_rr_nnnn ? OP_SRC_OPERAND16 : is_ldd_hl_a ? OP_SRC_REG16 : + is_bit_n_r ? OP_SRC_REG8 : op_src_t'('X); assign reg8_src_o = reg8_src;