svgb/rtl/cpu/cpu.sv

283 lines
9.2 KiB
Systemverilog

`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