`include "cpu_pkg.svh" import cpu_pkg::*; module idec ( input logic [7:0] instr_i[2:0], input logic is_ex1_i, input logic is_ex2_i, input logic is_ex3_i, output logic req_instr1_o, output logic req_instr2_o, output logic req_ex2_o, output logic req_ex3_o, output bus_ctrl_t bus_x_ctrl_o, output bus_ctrl_t bus_y_ctrl_o, output bus16_ctrl_t bus_p_ctrl_o, output bus16_ctrl_t bus_q_ctrl_o, output reg8_t reg8_src_o, output reg8_t reg8_dest_o, output reg16_t reg16_sel_o, output alu_ctrl_t alu_ctrl_o, output logic alu16_inc_o, output logic alu16_dec_o, output addr_src_t addr_src_o, output logic pc_we_o, output logic pc_we_cc_o, output cc_t cc_o, output pc_src_t pc_src_o, output logic instr_undef_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_alu_a_r; logic is_alu_a_n; logic is_ld_sp_nnnn; logic is_ld_rr_nnnn; logic is_ld_pnnnn_a; logic is_ldd_hl_a; logic is_ldi_hl_a; logic is_ldd_a_hl; logic is_ldi_a_hl; logic is_cb; logic is_ld_r_r; logic is_ld_r_n; logic is_ldh_c_a; logic is_ldh_n_a; logic is_ldh_a_n; logic is_ld_rr_a; logic is_ld_a_pbc; logic is_ld_a_pde; logic is_ld_a_nn; logic is_bit_n_r; logic is_shift_r; logic is_rla; logic is_inc_r; logic is_dec_r; logic is_jr_cc_nn; logic is_jr_nn; logic is_call_nn; logic is_ret; logic is_push_rr; logic is_pop_rr; logic is_inc_rr; logic is_dec_rr; reg8_t reg8_src; reg8_t reg8_dest; reg16_t reg16_sel; assign req_instr1_o = is_ld_sp_nnnn | is_ld_rr_nnnn | is_call_nn | is_ld_pnnnn_a | is_cb | is_jr_nn | is_jr_cc_nn | is_ld_r_n | is_ldh_n_a | is_ldh_a_n | is_alu_a_n; assign req_instr2_o = is_ld_sp_nnnn | is_ld_rr_nnnn | is_call_nn | is_ld_pnnnn_a; assign req_ex2_o = is_call_nn | is_ret | is_push_rr | is_pop_rr | ((is_ld_r_r | is_alu_a_r) & (reg8_src == REG8_PHL)); assign req_ex3_o = is_ret | is_pop_rr; assign dec_x = instr_i[0][7:6]; assign dec_y = instr_i[0][5:3]; assign dec_z = instr_i[0][2:0]; assign dec_p = instr_i[0][5:4]; assign dec_q = instr_i[0][3]; assign is_jr_nn = instr_i[0] == 8'h18; assign is_cb = instr_i[0] == 8'hCB; assign is_call_nn = instr_i[0] == 8'hCD; assign is_ret = instr_i[0] == 8'hC9; assign is_ldh_c_a = instr_i[0] == 8'hE2; assign is_ldh_n_a = instr_i[0] == 8'hE0; assign is_ldh_a_n = instr_i[0] == 8'hF0; assign is_ld_pnnnn_a = instr_i[0] == 8'hEA; assign is_jr_cc_nn = (dec_x == 2'h0) & (dec_z == 2'h0) & dec_y[2]; 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_ldi_hl_a = (dec_x == 2'h0) & (dec_z == 3'h2) & ~dec_q & (dec_p == 2'h2); assign is_ldd_hl_a = (dec_x == 2'h0) & (dec_z == 3'h2) & ~dec_q & (dec_p == 2'h3); assign is_ld_a_pbc = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p == 2'h0); assign is_ld_a_pde = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p == 2'h1); assign is_ldi_a_hl = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p == 2'h2); assign is_ldd_a_hl = (dec_x == 2'h0) & (dec_z == 3'h2) & dec_q & (dec_p == 2'h3); assign is_inc_rr = (dec_x == 2'h0) & (dec_z == 3'h3) & ~dec_q; assign is_dec_rr = (dec_x == 2'h0) & (dec_z == 3'h3) & dec_q; assign is_inc_r = (dec_x == 2'h0) & (dec_z == 3'h4); assign is_dec_r = (dec_x == 2'h0) & (dec_z == 3'h5); assign is_ld_r_n = (dec_x == 2'h0) & (dec_z == 3'h6); assign is_ld_rr_a = '0; assign is_rla = (dec_x == 3'h0) & (dec_z == 3'h7) & (dec_y == 3'h2); assign is_ld_r_r = (dec_x == 2'h1) & ((dec_z != 3'h6) | (dec_y != 3'h6)); assign is_alu_a_r = (dec_x == 2'h2); assign is_pop_rr = (dec_x == 2'h3) & (dec_z == 3'h1) & ~dec_q; assign is_push_rr = (dec_x == 2'h3) & (dec_z == 3'h5) & ~dec_q; assign is_alu_a_n = (dec_x == 2'h3) & (dec_z == 3'h6); assign is_bit_n_r = (is_cb & instr_i[1][7:6] == 2'h1); assign is_shift_r = (is_cb & instr_i[1][7:6] == 2'h0) | is_rla; assign bus_x_ctrl_o.src = (is_ld_sp_nnnn ) ? BUS_SRC_OPERAND8_H : (is_ld_rr_nnnn ) ? BUS_SRC_OPERAND8_H : (is_ld_pnnnn_a ) ? BUS_SRC_A : (is_ldd_hl_a ) ? BUS_SRC_A : (is_ldi_hl_a ) ? BUS_SRC_A : (is_ldh_c_a ) ? BUS_SRC_A : (is_ldh_n_a ) ? BUS_SRC_A : (is_ldh_a_n ) ? BUS_SRC_MEM : (is_alu_a_r & (reg8_src == REG8_A )) ? BUS_SRC_A : (is_alu_a_r & (reg8_src == REG8_PHL)) ? BUS_SRC_MEM : (is_alu_a_r ) ? BUS_SRC_REG8 : (is_alu_a_n ) ? BUS_SRC_OPERAND8_L : (is_bit_n_r & (reg8_src == REG8_A )) ? BUS_SRC_A : (is_bit_n_r & (reg8_src != REG8_A )) ? BUS_SRC_REG8 : (is_ld_r_n ) ? BUS_SRC_OPERAND8_L : (is_inc_r ) ? BUS_SRC_REG8 : (is_dec_r ) ? BUS_SRC_REG8 : (is_ld_r_r & (reg8_src == REG8_A )) ? BUS_SRC_A : (is_ld_r_r & (reg8_src == REG8_PHL)) ? BUS_SRC_MEM : (is_ld_r_r ) ? BUS_SRC_REG8 : (is_ld_a_pbc ) ? BUS_SRC_MEM : (is_ld_a_pde ) ? BUS_SRC_MEM : (is_call_nn & ~is_ex2_i ) ? BUS_SRC_PC_L : (is_call_nn & is_ex2_i ) ? BUS_SRC_PC_H : (is_push_rr & ~is_ex2_i ) ? BUS_SRC_REG16_L : (is_push_rr & is_ex2_i ) ? BUS_SRC_REG16_H : (is_pop_rr ) ? BUS_SRC_MEM : (is_ret ) ? BUS_SRC_MEM : (is_shift_r & (reg8_src == REG8_A )) ? BUS_SRC_A : (is_shift_r & (reg8_src != REG8_A )) ? BUS_SRC_REG8 : BUS_SRC_MEM; assign bus_x_ctrl_o.dst = is_ld_sp_nnnn ? BUS_DST_SP_H : is_ld_rr_nnnn ? BUS_DST_REG16_H : is_ld_pnnnn_a ? BUS_DST_MEM : is_ldd_hl_a ? BUS_DST_MEM : is_ldi_hl_a ? BUS_DST_MEM : is_ldh_c_a ? BUS_DST_MEM : is_ldh_n_a ? BUS_DST_MEM : is_ldh_a_n ? BUS_DST_ALU : is_alu_a_r ? BUS_DST_ALU : is_alu_a_n ? BUS_DST_ALU : is_bit_n_r ? BUS_DST_ALU : is_inc_r ? BUS_DST_ALU : is_dec_r ? BUS_DST_ALU : is_ld_a_pbc ? BUS_DST_ALU : is_ld_a_pde ? BUS_DST_ALU : is_call_nn ? BUS_DST_MEM : is_push_rr ? BUS_DST_MEM : is_pop_rr & is_ex2_i ? BUS_DST_REG16_H : is_pop_rr & is_ex3_i ? BUS_DST_REG16_L : is_ret & is_ex2_i ? BUS_DST_PC_H : is_ret & is_ex3_i ? BUS_DST_PC_L : (is_ld_r_n & (reg8_dest == REG8_A )) ? BUS_DST_ALU : (is_ld_r_n & (reg8_dest != REG8_A )) ? BUS_DST_REG8 : (is_ld_r_r & (reg8_dest == REG8_A )) ? BUS_DST_ALU : (is_ld_r_r & (reg8_dest == REG8_PHL)) ? BUS_DST_MEM : (is_ld_r_r ) ? BUS_DST_REG8 : (is_shift_r ) ? BUS_DST_ALU : BUS_DST_SP_H; assign bus_x_ctrl_o.wen = is_ld_sp_nnnn | is_ld_rr_nnnn | is_alu_a_n | is_ldd_hl_a | is_ldi_hl_a | is_bit_n_r | is_ld_r_n | is_ldh_c_a | is_ldh_n_a | is_ldh_a_n | is_call_nn | is_ret | is_push_rr | (is_pop_rr & (is_ex2_i | is_ex3_i)) | (is_ret & (is_ex2_i | is_ex3_i)) | is_shift_r | is_inc_r | is_dec_r | is_ld_pnnnn_a | (is_ld_r_r & (reg8_src != REG8_PHL)) | (is_ld_r_r & (reg8_src == REG8_PHL) & is_ex2_i) | (is_alu_a_r & (reg8_src != REG8_PHL)) | (is_alu_a_r & (reg8_src == REG8_PHL) & is_ex2_i); assign bus_y_ctrl_o.src = is_ld_sp_nnnn ? BUS_SRC_OPERAND8_L : is_ld_rr_nnnn ? BUS_SRC_OPERAND8_L : is_inc_r ? BUS_SRC_ALU : is_dec_r ? BUS_SRC_ALU : is_shift_r ? BUS_SRC_ALU : is_pop_rr & is_ex2_i ? BUS_SRC_REG16_L : is_pop_rr & is_ex3_i ? BUS_SRC_REG16_H : is_ret & is_ex2_i ? BUS_SRC_PC_L : is_ret & is_ex3_i ? BUS_SRC_PC_H : BUS_SRC_MEM; assign bus_y_ctrl_o.dst = is_ld_sp_nnnn ? BUS_DST_SP_L : is_ld_rr_nnnn ? BUS_DST_REG16_L : is_inc_r ? BUS_DST_REG8 : is_dec_r ? BUS_DST_REG8 : is_shift_r ? BUS_DST_REG8 : is_pop_rr & is_ex2_i ? BUS_DST_REG16_L : is_pop_rr & is_ex3_i ? BUS_DST_REG16_H : is_ret & is_ex2_i ? BUS_DST_PC_L : is_ret & is_ex3_i ? BUS_DST_PC_H : BUS_DST_REG8; assign bus_y_ctrl_o.wen = is_ld_sp_nnnn | is_ld_rr_nnnn | (is_inc_r & reg8_dest != REG8_A) | (is_shift_r & reg8_dest != REG8_A) | (is_dec_r & reg8_dest != REG8_A) | (is_pop_rr & (is_ex2_i | is_ex3_i)) | (is_ret & (is_ex2_i | is_ex3_i)); assign bus_p_ctrl_o.src = is_ldd_hl_a ? BUS16_SRC_REG16 : is_ldi_hl_a ? BUS16_SRC_REG16 : is_call_nn ? BUS16_SRC_SP : is_ret ? BUS16_SRC_SP : is_push_rr ? BUS16_SRC_SP : is_pop_rr ? BUS16_SRC_SP : is_inc_rr & (reg16_sel == REG16_SP_AF) ? BUS16_SRC_SP : is_inc_rr & (reg16_sel != REG16_SP_AF) ? BUS16_SRC_REG16 : is_dec_rr & (reg16_sel == REG16_SP_AF) ? BUS16_SRC_SP : is_dec_rr & (reg16_sel != REG16_SP_AF) ? BUS16_SRC_REG16 : BUS16_SRC_REG16; assign bus_p_ctrl_o.dst = BUS16_DST_ALU16; assign bus_p_ctrl_o.wen = is_ldd_hl_a | is_ldi_hl_a | is_call_nn | is_ret | is_push_rr | is_pop_rr | is_inc_rr | is_dec_rr; assign bus_q_ctrl_o.src = BUS16_SRC_ALU16; assign bus_q_ctrl_o.dst = is_ldd_hl_a ? BUS16_DST_REG16 : is_ldi_hl_a ? BUS16_DST_REG16 : is_call_nn ? BUS16_DST_SP : is_ret ? BUS16_DST_SP : is_push_rr ? BUS16_DST_SP : is_pop_rr ? BUS16_DST_SP : is_inc_rr & (reg16_sel == REG16_SP_AF) ? BUS16_DST_SP : is_inc_rr & (reg16_sel != REG16_SP_AF) ? BUS16_DST_REG16 : is_dec_rr & (reg16_sel == REG16_SP_AF) ? BUS16_DST_SP : is_dec_rr & (reg16_sel != REG16_SP_AF) ? BUS16_DST_REG16 : BUS16_DST_REG16; assign bus_q_ctrl_o.wen = is_ldd_hl_a | is_ldi_hl_a | is_call_nn | (is_ret & (is_ex1_i | is_ex2_i)) | is_push_rr | (is_pop_rr & (is_ex1_i | is_ex2_i)) | is_inc_rr | is_dec_rr; assign reg8_src = is_ldh_c_a ? REG8_C : is_rla ? REG8_A : is_inc_r ? reg8_dest : is_dec_r ? reg8_dest : is_cb ? reg8_t'(instr_i[1][2:0]) : reg8_t'(dec_z); assign reg8_dest = is_rla ? REG8_A : is_cb ? reg8_t'(instr_i[1][2:0]) : reg8_t'(dec_y); assign reg16_sel = is_ldd_hl_a ? REG16_HL : is_ldi_hl_a ? REG16_HL : is_ld_r_r & ((reg8_src == REG8_PHL) | (reg8_dest == REG8_PHL)) ? REG16_HL : is_alu_a_r & (reg8_src == REG8_PHL) ? REG16_HL : is_ld_a_pbc ? REG16_BC : is_ld_a_pde ? REG16_DE : reg16_t'(dec_p); assign reg8_src_o = reg8_src; assign reg8_dest_o = reg8_dest; assign reg16_sel_o = reg16_sel; assign alu_ctrl_o.alu_op_valid = is_alu_a_n | (is_alu_a_r & (reg8_src != REG8_PHL)) | (is_alu_a_r & (reg8_src == REG8_PHL) & is_ex2_i); assign alu_ctrl_o.alu_op = alu_op_t'(dec_y); assign alu_ctrl_o.shift_op_valid = is_shift_r; assign alu_ctrl_o.shift_op = is_rla ? SHIFT_OP_RL : shift_op_t'(instr_i[1][5:3]); assign alu_ctrl_o.bsr_op_valid = is_bit_n_r; assign alu_ctrl_o.bsr_op.b = is_bit_n_r; assign alu_ctrl_o.bsr_op.s = '0; assign alu_ctrl_o.bsr_op.r = '0; assign alu_ctrl_o.bsr_op.operand = instr_i[1][5:3]; assign alu_ctrl_o.incdec_op_valid = is_inc_r | is_dec_r; assign alu_ctrl_o.incdec_op.inc = is_inc_r; assign alu_ctrl_o.incdec_op.dec = is_dec_r; assign alu_ctrl_o.incdec_op.dst_a = reg8_dest == REG8_A; assign alu_ctrl_o.update_a = is_alu_a_n | (is_alu_a_r & (reg8_src != REG8_PHL)) | (is_alu_a_r & (reg8_src == REG8_PHL) & is_ex2_i) | (is_ld_r_n & (reg8_dest == REG8_A)) | (is_ld_r_r & (reg8_dest == REG8_A)) | (is_inc_r & (reg8_dest == REG8_A)) | (is_dec_r & (reg8_dest == REG8_A)) | is_ld_a_pbc | is_ld_a_pde | (is_shift_r & (reg8_dest == REG8_A)) | is_ldh_a_n; assign alu_ctrl_o.update_f = is_alu_a_n | is_bit_n_r | is_inc_r | is_dec_r | is_shift_r | (is_alu_a_r & (reg8_src != REG8_PHL)) | (is_alu_a_r & (reg8_src == REG8_PHL) & is_ex2_i); assign alu16_inc_o = is_ldi_hl_a | is_ret | is_pop_rr | is_inc_rr; assign alu16_dec_o = is_ldd_hl_a | is_call_nn | is_push_rr | is_dec_rr; assign pc_we_o = is_call_nn | (is_ret & (is_ex2_i | is_ex3_i)) | is_jr_nn; assign pc_we_cc_o = is_jr_cc_nn; assign cc_o = cc_t'(dec_y[1:0]); assign pc_src_o = is_ret ? PC_SRC_BUS : is_call_nn ? PC_SRC_OPERAND16 : PC_SRC_OPERAND8; assign addr_src_o = is_ldd_hl_a ? ADDR_SRC_REG16 : is_ldi_hl_a ? ADDR_SRC_REG16 : is_ld_a_pbc ? ADDR_SRC_REG16 : is_ld_a_pde ? ADDR_SRC_REG16 : is_ldh_c_a ? ADDR_SRC_REG8 : is_ldh_n_a ? ADDR_SRC_OPERAND8 : is_ldh_a_n ? ADDR_SRC_OPERAND8 : is_call_nn ? ADDR_SRC_SP : is_ret & is_ex3_i ? ADDR_SRC_BUS_P : is_ret ? ADDR_SRC_BUS_Q : is_push_rr ? ADDR_SRC_SP : is_pop_rr & is_ex3_i ? ADDR_SRC_BUS_P : is_pop_rr ? ADDR_SRC_BUS_Q : is_ld_r_r & ((reg8_src == REG8_PHL) | (reg8_dest == REG8_PHL)) ? ADDR_SRC_REG16 : is_alu_a_r & (reg8_src == REG8_PHL) ? ADDR_SRC_REG16 : is_ld_pnnnn_a ? ADDR_SRC_OPERAND16: ADDR_SRC_PC; assign instr_undef_o = ~( is_ld_sp_nnnn | is_alu_a_r | is_alu_a_n | is_ld_rr_nnnn | is_ldd_hl_a | is_ldi_hl_a | is_bit_n_r | is_jr_nn | is_jr_cc_nn | is_ld_r_n | is_ldh_c_a | is_inc_r | is_dec_r | is_ld_r_r | is_ldh_n_a | is_ldh_a_n | is_ld_a_pbc | is_ld_a_pde | is_call_nn | is_push_rr | is_pop_rr | (is_shift_r & (instr_i[1][5:3] == 3'h02)) | is_rla | is_inc_rr | is_dec_rr | is_ret | is_ld_pnnnn_a); endmodule : idec