2021-02-15 23:55:09 +01:00
|
|
|
`include "cpu_pkg.svh"
|
|
|
|
|
|
|
|
import cpu_pkg::*;
|
|
|
|
|
|
|
|
module cpu (
|
2023-10-02 00:00:56 +02:00
|
|
|
input logic clk,
|
|
|
|
input logic nreset,
|
2021-02-15 23:55:09 +01:00
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
output logic [15:0] addr_o,
|
|
|
|
input logic [ 7:0] rdata_i,
|
|
|
|
output logic we_o,
|
|
|
|
output logic [ 7:0] wdata_o
|
2021-02-15 23:55:09 +01:00
|
|
|
);
|
|
|
|
|
2023-10-02 00:00:56 +02:00
|
|
|
|
|
|
|
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:0] <= '0;
|
|
|
|
else if (sp_we[1])
|
|
|
|
sp_r[15:0] <= sp_next;
|
|
|
|
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;
|
|
|
|
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
|