svgb/rtl/cpu/idec.sv

348 lines
18 KiB
Systemverilog

`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 == 3'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 == 2'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