`include "cpu_pkg.svh" import cpu_pkg::*; module decode ( input logic [7:0] instr0_i, input logic [7:0] instr1_i, input logic [7:0] instr2_i, input state_t state_i, output logic need_instr1_o, output logic need_instr2_o, output logic is_multicycle_o, output logic undef_o, output logic sp_we_o, output sp_src_t sp_src_o, output logic alu_op_valid_o, output alu_op_t alu_op_o, output logic reg_write_alu_o, output logic rot_op_valid_o, output rot_op_t rot_op_o, output op_src_t op_src_o, output op_dest_t op_dest_o, output reg8_t reg8_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, output logic branch_always_o, output cc_t cc_o, output pc_src_t pc_src_o, output adr_src_t adr_src_o, output logic memory_we_o ); logic [1:0] dec_x; logic [2:0] dec_y; logic [2:0] dec_z; logic [1:0] dec_p; logic dec_q; logic is_cb; logic is_ld_r_r; logic is_ld_a_n; logic is_ld_r_n; logic is_ldh_c_a; logic is_ldh_n_a; logic is_ld_rr_a; logic is_ld_nn_a; logic is_ld_a_rr; logic is_ld_a_nn; logic is_ld_rr_nn; logic is_ld_sp_nn; logic is_ldd_hl_a; logic is_alu_a_r; logic is_bit_n_r; logic is_rot_r; logic is_inc_a; logic is_inc_r; logic is_jr_cc_n; logic is_call_nn; logic is_push_rr; reg8_t reg8_dest; reg8_t reg8_src; reg16_t reg16_src; assign dec_x = instr0_i[7:6]; assign dec_y = instr0_i[5:3]; assign dec_z = instr0_i[2:0]; assign dec_p = instr0_i[5:4]; assign dec_q = instr0_i[3]; assign is_cb = (instr0_i == 8'hCB); assign is_ld_r_r = (dec_x == 2'h1) & ((dec_z != 3'h6) | (dec_y != 3'h6)); assign is_ld_a_n = is_ld_r_n & (reg8_dest == REG8_A); assign is_ld_r_n = (dec_x == 2'h0) & (dec_z == 3'h6); assign is_ld_rr_nn = (dec_x == 2'h0) & (dec_z == 3'h1) & ~dec_q & (dec_p != 2'h3); assign is_ld_sp_nn = (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_ld_rr_a = (dec_x == 2'h0) & (dec_z == 3'h2) & ~dec_q & (dec_p != 2'h3); assign is_ld_nn_a = (dec_x == 2'h0) & (dec_z == 3'h2) & ~dec_q & (dec_p == 2'h2); assign is_ld_a_rr = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p != 2'h3); assign is_ld_a_nn = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p == 2'h3); assign is_ldh_c_a = instr0_i == 8'hE2; assign is_ldh_n_a = instr0_i == 8'hE0; assign is_alu_a_r = (dec_x == 3'h2); assign is_bit_n_r = (is_cb & instr1_i[7:6] == 2'h1); assign is_rot_r = (is_cb & instr1_i[7:6] == 2'h0); assign is_inc_a = is_inc_r & (reg8_dest == REG8_A); 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 is_push_rr = (dec_x == 2'h3) & (dec_z == 3'h5) && ~dec_q; assign reg8_src = is_cb ? reg8_t'(instr1_i[2:0]) : is_ldh_c_a ? REG8_C : is_inc_r ? reg8_t'(dec_y) : (is_push_rr & state_i == ST2_EXEC) ? reg8_t'({dec_p, 1'b0}) : (is_push_rr & state_i == ST3_EXEC) ? reg8_t'({dec_p, 1'b1}) : reg8_t'(dec_z); assign reg8_dest = is_rot_r ? reg8_t'(dec_z) : reg8_t'(dec_y); assign reg16_src = is_ldd_hl_a ? REG16_HL : reg16_t'(dec_p); 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 | is_push_rr; 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_call_nn | is_push_rr | (is_rot_r & (instr1_i[5:3] == 3'h02))); assign sp_we_o = is_ld_sp_nn | is_call_nn | is_push_rr; assign sp_src_o = is_ld_sp_nn ? SP_SRC_OPERAND16 : is_call_nn ? SP_SRC_DEC : is_push_rr ? 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 : is_ld_a_n ? ALU_OP_NOP : is_ld_a_nn ? ALU_OP_NOP : is_ld_a_rr ? ALU_OP_NOP : is_inc_a ? ALU_OP_INC : is_inc_r ? ALU_OP_INCR : alu_op_t'({1'b0, dec_y}); assign reg_write_alu_o = is_inc_r | is_rot_r; assign rot_op_valid_o = is_rot_r; assign rot_op_o = rot_op_t'(instr1_i[5:3]); assign op_dest_o = (is_ld_r_r & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY : (is_ld_r_n & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY : (is_ld_r_r & reg8_dest == REG8_A) ? OP_DEST_A : is_ld_r_r ? OP_DEST_REG8 : is_ld_a_n ? OP_DEST_A : is_ld_a_rr ? OP_DEST_A : is_ld_a_nn ? OP_DEST_A : is_ld_r_n ? OP_DEST_REG8 : is_ldh_c_a ? OP_DEST_MEMORY : is_ldh_n_a ? OP_DEST_MEMORY : is_ld_rr_nn ? OP_DEST_REG16 : 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 : is_push_rr ? OP_DEST_MEMORY : is_rot_r ? OP_DEST_REG8 : op_dest_t'('X); assign op_src_o = (is_ld_r_r & reg8_src == REG8_A) ? OP_SRC_A : (is_alu_a_r & reg8_src == REG8_A) ? OP_SRC_A : (is_alu_a_r & reg8_src != REG8_A) ? OP_SRC_REG8 : (is_ld_r_r & reg8_src == REG8_PHL) ? OP_SRC_MEMORY : is_inc_r ? OP_SRC_REG8 : is_ld_r_n ? OP_SRC_OPERAND8 : is_ldh_c_a ? OP_SRC_A : is_ldh_n_a ? OP_SRC_A : is_ld_a_rr ? OP_SRC_MEMORY : is_ld_a_nn ? OP_SRC_MEMORY : is_ld_rr_nn ? OP_SRC_OPERAND16 : is_ldd_hl_a ? OP_SRC_REG16 : is_bit_n_r ? OP_SRC_REG8 : is_rot_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 : (is_push_rr & reg16_src != REG16_SP_AF) ? OP_SRC_REG8 : (is_push_rr & reg16_src == REG16_SP_AF & state_i == ST2_EXEC) ? OP_SRC_A : (is_push_rr & reg16_src == REG16_SP_AF & state_i == ST3_EXEC) ? OP_SRC_F : op_src_t'('X); assign reg8_dest_o = reg8_dest; assign reg8_src_o = reg8_src; assign reg16_src_o = reg16_src; assign reg16_dest_o = reg16_src; 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 : (is_ld_r_r & reg8_src == REG8_PHL) ? ADR_SRC_HL : is_ldd_hl_a ? ADR_SRC_HL : (is_ld_r_n & reg8_dest == REG8_PHL) ? ADR_SRC_HL : is_ldh_c_a ? ADR_SRC_REG8 : is_ldh_n_a ? ADR_SRC_OPERAND8 : is_ld_nn_a ? ADR_SRC_OPERAND16 : 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 : is_push_rr ? 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) | is_call_nn | is_push_rr; endmodule : decode