`include "cpu_pkg.svh" import cpu_pkg::*; module cpu ( input logic clk, input logic nreset, output logic [15:0] addr_o, input logic [ 7:0] rdata_i, output logic we_o, output logic [ 7:0] wdata_o ); logic instr_valid; logic [ 7:0] instr[2:0]; logic incr_pc; logic pc_we; logic [15:0] pc_r; logic [15:0] pc_next; logic [15:0] pc_bus; cc_t ctrl_cc; logic ctrl_pc_we; logic ctrl_pc_we_cc; pc_src_t ctrl_pc_src; logic [ 1:0] sp_we; logic [15:0] sp_r; logic [15:0] sp_next; reg8_t reg8_rsel; reg8_t reg8_wsel; logic reg8_we; logic [7:0] reg8_wdata; logic [7:0] reg8_rdata; reg16_t reg16_sel; logic reg16_we; logic [15:0] reg16_wdata; logic [15:0] reg16_rdata; addr_src_t addr_src; logic [ 7:0] reg_a; logic [ 7:0] reg_f; logic alu_update_a; logic alu_update_f; alu_ctrl_t ctrl_alu_ctrl; alu_ctrl_t alu_ctrl; logic [ 7:0] alu_operand_in; logic [ 7:0] alu_operand_out; logic alu16_en; logic [15:0] alu16_in; logic [15:0] alu16_out; logic alu16_inc; logic alu16_dec; bus_ctrl_t bus_x_ctrl; bus_ctrl_t bus_y_ctrl; bus16_ctrl_t bus_p_ctrl; bus16_ctrl_t bus_q_ctrl; logic [ 7:0] bus_x; logic [ 7:0] bus_y; logic [15:0] bus_p; logic [15:0] bus_q; logic cc_true; always_ff @(posedge clk or negedge nreset) begin if (!nreset) pc_r <= '0; else if (pc_we) pc_r <= pc_next; end assign pc_we = ctrl_pc_we | (ctrl_pc_we_cc & cc_true); assign pc_next = (ctrl_pc_src == PC_SRC_OPERAND8 ) ? (pc_r + {{8{instr[1][7]}}, instr[1]}) : (ctrl_pc_src == PC_SRC_OPERAND16) ? {instr[2], instr[1]} : (ctrl_pc_src == PC_SRC_BUS) ? pc_bus : pc_r + 16'h01; assign cc_true = ((ctrl_cc == CC_NZ) & ~reg_f[7]) | ((ctrl_cc == CC_Z) & reg_f[7]) | ((ctrl_cc == CC_NC) & ~reg_f[4]) | ((ctrl_cc == CC_C) & reg_f[4]); assign pc_bus[15:8] = ({8{bus_x_ctrl.dst == BUS_DST_PC_H}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_PC_H}} & bus_y); assign pc_bus[ 7:0] = ({8{bus_x_ctrl.dst == BUS_DST_PC_L}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_PC_L}} & bus_y); always_ff @(posedge clk or negedge nreset) begin if (!nreset) sp_r[15:8] <= '0; else if (sp_we[1]) sp_r[15:8] <= sp_next[15:8]; end always_ff @(posedge clk or negedge nreset) begin if (!nreset) sp_r[ 7:0] <= '0; else if (sp_we[0]) sp_r[ 7:0] <= sp_next[7:0]; end assign sp_we[1] = instr_valid & ( (bus_x_ctrl.wen & (bus_x_ctrl.dst == BUS_DST_SP_H)) | (bus_y_ctrl.wen & (bus_y_ctrl.dst == BUS_DST_SP_H)) | (bus_p_ctrl.wen & (bus_p_ctrl.dst == BUS16_DST_SP)) | (bus_q_ctrl.wen & (bus_q_ctrl.dst == BUS16_DST_SP))); assign sp_we[0] = instr_valid & ( (bus_x_ctrl.wen & (bus_x_ctrl.dst == BUS_DST_SP_L)) | (bus_y_ctrl.wen & (bus_y_ctrl.dst == BUS_DST_SP_L)) | (bus_p_ctrl.wen & (bus_p_ctrl.dst == BUS16_DST_SP)) | (bus_q_ctrl.wen & (bus_q_ctrl.dst == BUS16_DST_SP))); assign sp_next[15:8] = ({8{bus_x_ctrl.dst == BUS_DST_SP_H}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_SP_H}} & bus_y) | ({8{bus_p_ctrl.dst == BUS16_DST_SP}} & bus_p[15:8]) | ({8{bus_q_ctrl.dst == BUS16_DST_SP}} & bus_q[15:8]); assign sp_next[ 7:0] = ({8{bus_x_ctrl.dst == BUS_DST_SP_L}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_SP_L}} & bus_y) | ({8{bus_p_ctrl.dst == BUS16_DST_SP}} & bus_p[ 7:0]) | ({8{bus_q_ctrl.dst == BUS16_DST_SP}} & bus_q[ 7:0]); ctrl ctrl_inst ( .clk (clk), .nreset (nreset), .rdata_i (rdata_i), .instr_valid_o(instr_valid), .instr_o (instr), .pc_we_o (ctrl_pc_we), .pc_we_cc_o (ctrl_pc_we_cc), .pc_src_o (ctrl_pc_src), .cc_o (ctrl_cc), .reg8_src_o (reg8_rsel), .reg8_dest_o (reg8_wsel), .reg16_sel_o (reg16_sel), .alu_ctrl_o (ctrl_alu_ctrl), .addr_src_o (addr_src), .alu16_inc_o (alu16_inc), .alu16_dec_o (alu16_dec), .bus_x_ctrl_o (bus_x_ctrl), .bus_y_ctrl_o (bus_y_ctrl), .bus_p_ctrl_o (bus_p_ctrl), .bus_q_ctrl_o (bus_q_ctrl) ); regbank regbank_inst ( .clk (clk), .nreset (nreset), .reg16_wselect_i (reg16_sel), .reg16_rselect_i (reg16_sel), .reg16_we_i (reg16_we), .reg16_wdata_i (reg16_wdata), .reg16_rdata_o (reg16_rdata), .reg8_wselect_i (reg8_wsel), .reg8_we_i (reg8_we), .reg8_wdata_i (reg8_wdata), .reg8_rselect_i (reg8_rsel), .reg8_rdata_o (reg8_rdata) ); assign reg8_we = instr_valid & ( (bus_x_ctrl.wen & (bus_x_ctrl.dst == BUS_DST_REG8)) | (bus_y_ctrl.wen & (bus_y_ctrl.dst == BUS_DST_REG8))); assign reg8_wdata = ({8{bus_x_ctrl.dst == BUS_DST_REG8}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_REG8}} & bus_y); assign reg16_we = instr_valid & ( (bus_x_ctrl.wen & (bus_x_ctrl.dst == BUS_DST_REG16_H | bus_x_ctrl.dst == BUS_DST_REG16_L)) | (bus_y_ctrl.wen & (bus_y_ctrl.dst == BUS_DST_REG16_H | bus_y_ctrl.dst == BUS_DST_REG16_L)) | (bus_p_ctrl.wen & (bus_p_ctrl.dst == BUS16_DST_REG16)) | (bus_q_ctrl.wen & (bus_q_ctrl.dst == BUS16_DST_REG16))); assign reg16_wdata[15:8] = ({8{bus_x_ctrl.dst == BUS_DST_REG16_H}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_REG16_H}} & bus_y) | ({8{bus_p_ctrl.dst == BUS16_DST_REG16}} & bus_p[15:8]) | ({8{bus_q_ctrl.dst == BUS16_DST_REG16}} & bus_q[15:8]); assign reg16_wdata[ 7:0] = ({8{bus_x_ctrl.dst == BUS_DST_REG16_L}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_REG16_L}} & bus_y) | ({8{bus_p_ctrl.dst == BUS16_DST_REG16}} & bus_p[ 7:0]) | ({8{bus_q_ctrl.dst == BUS16_DST_REG16}} & bus_q[ 7:0]); alu alu_inst ( .clk (clk), .nreset (nreset), .alu_ctrl_i (alu_ctrl), .operand_in_i (alu_operand_in), .operand_out_o(alu_operand_out), .reg_a_o (reg_a), .reg_f_o (reg_f) ); always_comb begin alu_ctrl = ctrl_alu_ctrl; alu_ctrl.update_a = instr_valid & alu_ctrl.update_a; alu_ctrl.update_f = instr_valid & alu_ctrl.update_f; end assign alu_operand_in = ({8{bus_x_ctrl.dst == BUS_DST_ALU}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_ALU}} & bus_y); alu16 alu16_inst ( .operand_in_i (alu16_in), .operand_out_o(alu16_out), .increment_i (alu16_inc), .decrement_i (alu16_dec) ); assign alu16_en = alu16_inc | alu16_dec; assign alu16_in = ({16{bus_p_ctrl.dst == BUS16_DST_ALU16}} & bus_p) | ({16{bus_q_ctrl.dst == BUS16_DST_ALU16}} & bus_q); assign addr_o = ({16{addr_src == ADDR_SRC_PC }} & pc_r ) | ({16{addr_src == ADDR_SRC_SP }} & sp_r ) | ({16{addr_src == ADDR_SRC_REG16 }} & reg16_rdata) | ({16{addr_src == ADDR_SRC_REG8 }} & { 8'hFF, reg8_rdata}) | ({16{addr_src == ADDR_SRC_BUS_P }} & bus_p ) | ({16{addr_src == ADDR_SRC_BUS_Q }} & bus_q ) | ({16{addr_src == ADDR_SRC_OPERAND8 }} & { 8'hFF, instr[1] }) | ({16{addr_src == ADDR_SRC_OPERAND16}} & {instr[2], instr[1] }); assign we_o = instr_valid & ( (bus_x_ctrl.wen & bus_x_ctrl.dst == BUS_DST_MEM) | (bus_y_ctrl.wen & bus_y_ctrl.dst == BUS_DST_MEM)); assign wdata_o = ({8{bus_x_ctrl.dst == BUS_DST_MEM}} & bus_x) | ({8{bus_y_ctrl.dst == BUS_DST_MEM}} & bus_y); `define INST_BUS(x) \ assign bus_``x = ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_OPERAND8_H)}} & instr[2]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_OPERAND8_L)}} & instr[1]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_REG8 )}} & reg8_rdata) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_A )}} & reg_a) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_PC_H )}} & pc_r[15:8]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_PC_L )}} & pc_r[ 7:0]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_REG16_H )}} & reg16_rdata[15:8]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_REG16_L )}} & reg16_rdata[ 7:0]) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_MEM )}} & rdata_i ) | \ ({8{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS_SRC_ALU )}} & alu_operand_out); `INST_BUS(x); `INST_BUS(y); `undef INST_BUS `define INST_BUS16(x) \ assign bus_``x = ({16{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS16_SRC_REG16)}} & reg16_rdata) | \ ({16{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS16_SRC_ALU16)}} & alu16_out ) | \ ({16{bus_``x``_ctrl.wen & (bus_``x``_ctrl.src == BUS16_SRC_SP )}} & sp_r); `INST_BUS16(p); `INST_BUS16(q); `undef INST_BUS16 endmodule : cpu