From f6e68231fdb4ac29338da00677886af57fbfc4ef Mon Sep 17 00:00:00 2001 From: Koray Yanik Date: Mon, 22 Feb 2021 23:07:10 +0000 Subject: [PATCH] Implement call nn --- rtl/cpu/control.sv | 23 ++++++++++++++++------- rtl/cpu/cpu.sv | 3 +++ rtl/cpu/cpu_pkg.svh | 15 +++++++++++---- rtl/cpu/decode.sv | 26 +++++++++++++++++++------- 4 files changed, 49 insertions(+), 18 deletions(-) diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv index b74bf09..ebce11c 100644 --- a/rtl/cpu/control.sv +++ b/rtl/cpu/control.sv @@ -77,12 +77,14 @@ module control ( logic decoder_alu_op_valid; logic decoder_memory_we; adr_src_t decoder_adr_src; + logic decoder_sp_we; logic is_undef; logic pc_incr; logic instr_valid; logic branch_taken; logic branch_cc_true; + logic branch_always; sp_src_t sp_src; pc_src_t pc_src; @@ -108,10 +110,15 @@ module control ( `DEF_FF(operand1_r, operand1_next, operand1_we, '0); assign pc_we = (nreset_r & ~is_undef & ~halted_r) & (pc_incr | branch_taken); - assign pc_next = (branch_taken & pc_src == PC_SRC_OPERAND8) ? (pc_r + {{8{operand0_r[7]}}, operand0_r}) : - (pc_r + 16'b1); + assign pc_next = (branch_taken & pc_src == PC_SRC_OPERAND8) ? (pc_r + {{8{operand0_r[7]}}, operand0_r}) : + (branch_taken & pc_src == PC_SRC_OPERAND16) ? {operand1_r, operand0_r} : + (pc_r + 16'b1); - assign sp_next = (sp_src == SP_SRC_OPERAND16) ? {operand1_r, operand0_r} : '0; + assign sp_we = instr_valid & decoder_sp_we; + assign sp_next = (sp_src == SP_SRC_OPERAND16) ? {operand1_r, operand0_r} : + (sp_src == SP_SRC_INC) ? (sp_r + 16'h01) : + (sp_src == SP_SRC_DEC) ? (sp_r + 16'hFFFF) : + '0; assign instr_we = (state_r == ST1_DEC); assign instr_next = rdata_i; @@ -135,7 +142,8 @@ module control ( 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; + ST4_EXEC: state_next = decoder_is_multicycle ? ST5_EXEC : ST0_ADDR; + ST5_EXEC: state_next = ST0_ADDR; endcase end @@ -150,7 +158,7 @@ module control ( .is_multicycle_o(decoder_is_multicycle), .undef_o (decoder_is_undef), - .sp_we_o (sp_we), + .sp_we_o (decoder_sp_we), .sp_src_o (sp_src), .alu_op_valid_o(decoder_alu_op_valid), @@ -168,6 +176,7 @@ module control ( .memory_we_o (decoder_memory_we), .adr_src_o (decoder_adr_src), + .branch_always_o(branch_always), .cc_o (cc), .pc_src_o (pc_src) ); @@ -177,12 +186,12 @@ module control ( assign decoder_instr2_selected = (state_r == ST3_DEC) ? rdata_i : operand1_r; assign is_undef = instr_valid & decoder_is_undef; - assign instr_valid = (state_r == ST2_EXEC | state_r == ST3_EXEC | state_r == ST4_EXEC); + assign instr_valid = (state_r == ST2_EXEC | state_r == ST3_EXEC | state_r == ST4_EXEC | state_r == ST5_EXEC); assign alu_op_valid_o = decoder_alu_op_valid & instr_valid; assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2); - assign branch_taken = instr_valid & (pc_src != PC_SRC_SEQ) & branch_cc_true; + assign branch_taken = instr_valid & (pc_src != PC_SRC_SEQ) & (branch_cc_true | branch_always); assign branch_cc_true = ((cc == CC_NZ) & ~f_i[7]) | ((cc == CC_Z) & f_i[7]) | ((cc == CC_NC) & ~f_i[4]) | diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv index 46b5020..1dcbc28 100644 --- a/rtl/cpu/cpu.sv +++ b/rtl/cpu/cpu.sv @@ -117,6 +117,8 @@ module cpu ( (op_src == OP_SRC_OPERAND8) ? operand8 : (op_src == OP_SRC_REG8) ? reg8_rdata : (op_src == OP_SRC_MEMORY) ? rdata_i : + (op_src == OP_SRC_PC_L) ? pc[7:0] : + (op_src == OP_SRC_PC_H) ? pc[15:8] : 'X; assign reg8_we = instr_valid & (op_dest == OP_DEST_REG8); @@ -126,6 +128,7 @@ module cpu ( assign reg16_rselect2 = reg16_wselect; assign address_o = (adr_src == ADR_SRC_HL) ? hl : + (adr_src == ADR_SRC_SP) ? sp : (adr_src == ADR_SRC_REG8) ? {8'hFF, reg8_rdata} : (adr_src == ADR_SRC_REG16) ? reg16_rdata : (adr_src == ADR_SRC_OPERAND8) ? {8'hFF, operand8} : diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh index f803cd5..4e34027 100644 --- a/rtl/cpu/cpu_pkg.svh +++ b/rtl/cpu/cpu_pkg.svh @@ -11,7 +11,8 @@ package cpu_pkg; ST2_DEC, ST3_DEC, ST3_EXEC, - ST4_EXEC + ST4_EXEC, + ST5_EXEC } state_t; typedef enum logic [2:0] { @@ -66,7 +67,9 @@ package cpu_pkg; OP_SRC_OPERAND8, OP_SRC_MEMORY, OP_SRC_OPERAND16, - OP_SRC_REG16 + OP_SRC_REG16, + OP_SRC_PC_L, + OP_SRC_PC_H } op_src_t; typedef enum { @@ -77,12 +80,15 @@ package cpu_pkg; } op_dest_t; typedef enum { - SP_SRC_OPERAND16 + SP_SRC_OPERAND16, + SP_SRC_INC, + SP_SRC_DEC } sp_src_t; typedef enum { ADR_SRC_PC, ADR_SRC_HL, + ADR_SRC_SP, ADR_SRC_REG8, // extended with FF ADR_SRC_REG16, ADR_SRC_OPERAND8, // extended with FF @@ -91,7 +97,8 @@ package cpu_pkg; typedef enum { PC_SRC_SEQ, - PC_SRC_OPERAND8 + PC_SRC_OPERAND8, + PC_SRC_OPERAND16 } pc_src_t; endpackage diff --git a/rtl/cpu/decode.sv b/rtl/cpu/decode.sv index 54f614a..a1463ff 100644 --- a/rtl/cpu/decode.sv +++ b/rtl/cpu/decode.sv @@ -29,6 +29,7 @@ module decode ( output reg16_t reg16_dest_o, output reg16_t reg16_src_o, + output logic branch_always_o, output cc_t cc_o, output pc_src_t pc_src_o, @@ -60,6 +61,7 @@ module decode ( logic is_inc_a; logic is_inc_r; logic is_jr_cc_n; + logic is_call_nn; reg8_t reg8_dest; reg8_t reg8_src; @@ -92,6 +94,7 @@ module decode ( assign is_inc_r = (dec_x == 2'h0) & (dec_z == 3'h4); assign is_jr_cc_n = (dec_x == 2'h0) & (dec_z == 2'h0) & dec_y[2]; + assign is_call_nn = (instr0_i == 8'hCD); assign reg8_src = is_cb ? reg8_t'(instr1_i[2:0]) : is_ldh_c_a ? REG8_C : @@ -99,14 +102,17 @@ module decode ( reg8_t'(dec_z); assign reg8_dest = reg8_t'(dec_y); - assign need_instr1_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn | is_cb | is_jr_cc_n | is_ld_r_n | is_ldh_n_a; - assign need_instr2_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn; - assign is_multicycle_o = is_ld_a_rr; + assign need_instr1_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn | is_call_nn | is_cb | is_jr_cc_n | is_ld_r_n | is_ldh_n_a; + assign need_instr2_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn | is_call_nn; + assign is_multicycle_o = is_ld_a_rr | is_call_nn; assign undef_o = ~(is_ldh_n_a | is_ld_r_r | is_ld_sp_nn | is_ld_rr_nn | is_alu_a_r | is_ldd_hl_a | is_bit_n_r | - is_jr_cc_n | is_ld_r_n | is_ldh_c_a | is_inc_r | is_ld_rr_a | is_ld_a_rr); + is_jr_cc_n | is_ld_r_n | is_ldh_c_a | is_inc_r | is_ld_rr_a | is_ld_a_rr | is_call_nn); - assign sp_we_o = is_ld_sp_nn & (state_i == ST4_EXEC); + assign sp_we_o = is_ld_sp_nn | is_call_nn; + assign sp_src_o = is_ld_sp_nn ? SP_SRC_OPERAND16 : + is_call_nn ? SP_SRC_DEC : + sp_src_t'('X); assign alu_op_valid_o = is_alu_a_r | is_bit_n_r | is_ld_a_n | is_ld_a_rr | is_ld_a_nn | is_inc_r; assign alu_op_o = is_bit_n_r ? ALU_OP_BIT : @@ -132,6 +138,7 @@ module decode ( is_ldd_hl_a ? OP_DEST_REG16 : is_inc_a ? OP_DEST_A : is_inc_r ? OP_DEST_REG8 : + is_call_nn ? OP_DEST_MEMORY : op_dest_t'('X); assign op_src_o = (is_ld_r_r & reg8_src == REG8_A) ? OP_SRC_A : @@ -147,6 +154,8 @@ module decode ( is_ld_rr_nn ? OP_SRC_OPERAND16 : is_ldd_hl_a ? OP_SRC_REG16 : is_bit_n_r ? OP_SRC_REG8 : + is_call_nn & (state_i == ST4_EXEC) ? OP_SRC_PC_L : + is_call_nn & (state_i == ST5_EXEC) ? OP_SRC_PC_H : op_src_t'('X); assign reg8_dest_o = reg8_dest; @@ -154,7 +163,8 @@ module decode ( assign reg16_src_o = is_ldd_hl_a ? REG16_HL : reg16_t'(dec_p); assign reg16_dest_o = is_ldd_hl_a ? REG16_HL : reg16_t'(dec_p); - assign pc_src_o = is_jr_cc_n ? PC_SRC_OPERAND8 : + assign pc_src_o = is_jr_cc_n ? PC_SRC_OPERAND8 : + is_call_nn ? PC_SRC_OPERAND16 : PC_SRC_SEQ; assign adr_src_o = (is_ld_r_r & reg8_dest == REG8_PHL) ? ADR_SRC_HL : @@ -167,10 +177,12 @@ module decode ( is_ld_a_nn ? ADR_SRC_OPERAND16 : is_ld_a_rr ? ADR_SRC_REG16 : is_ld_rr_a ? ADR_SRC_REG16 : + is_call_nn ? ADR_SRC_SP : ADR_SRC_PC; + assign branch_always_o = is_call_nn; assign cc_o = cc_t'(dec_y[1:0]); - assign memory_we_o = is_ldd_hl_a | is_ldh_c_a | is_ldh_n_a | is_ld_rr_a | (is_ld_r_n & reg8_dest == REG8_PHL) | (is_ld_r_r & reg8_dest == REG8_PHL); + assign memory_we_o = is_ldd_hl_a | is_ldh_c_a | is_ldh_n_a | is_ld_rr_a | (is_ld_r_n & reg8_dest == REG8_PHL) | (is_ld_r_r & reg8_dest == REG8_PHL) | is_call_nn; endmodule : decode