Initial register bank, support LD RR, $nnnn instructions
This commit is contained in:
parent
237a5f1489
commit
2937ff492b
@ -2,8 +2,10 @@ TB = tb_top
|
||||
SOURCES = gb.sv cpu.sv alu.sv registers.sv control.sv decode.sv rom.sv tb_top.sv clkgen.sv
|
||||
PATH_SRC = ../rtl:../rtl/cpu:../rtl/shared:../sim/tbench:../sim/shared
|
||||
|
||||
gb.sdb: cpu.sdb rom.sdb
|
||||
cpu.sdb: control.sdb registers.sdb alu.sdb
|
||||
control.sdb: decode.sdb
|
||||
gb.sdb: cpu.sdb rom.sdb cpu_pkg.sdb
|
||||
cpu.sdb: control.sdb registers.sdb alu.sdb cpu_pkg.sdb
|
||||
control.sdb: decode.sdb cpu_pkg.sdb
|
||||
alu.sdb: cpu_pkg.sdb
|
||||
registers.sdb: cpu_pkg.sdb
|
||||
|
||||
include ../synthflow/vivado/Makefile.rules
|
@ -25,15 +25,6 @@ module alu (
|
||||
logic [ 7:0] a_xor;
|
||||
logic [ 7:0] f_xor;
|
||||
|
||||
`define DEF_FF(register, next, we, rst_value) \
|
||||
always_ff @(posedge clk_i or negedge nreset_i) begin \
|
||||
if (~nreset_i) begin \
|
||||
register <= (rst_value); \
|
||||
end else if ((we)) begin \
|
||||
register <= (next); \
|
||||
end \
|
||||
end
|
||||
|
||||
`DEF_FF(a_r, a_next, a_we, '0);
|
||||
`DEF_FF(f_r, f_next, f_we, '0);
|
||||
|
||||
|
@ -21,7 +21,10 @@ module control (
|
||||
output logic alu_op_valid_o,
|
||||
output alu_op_t alu_op_o,
|
||||
output op_src_t op_src_o,
|
||||
output op_dest_t op_dest_o
|
||||
output op_dest_t op_dest_o,
|
||||
output reg16_t reg16_dest_o,
|
||||
|
||||
output adr_src_t adr_src_o
|
||||
);
|
||||
|
||||
logic nreset_r;
|
||||
@ -61,6 +64,7 @@ module control (
|
||||
logic decoder_need_instr1;
|
||||
logic decoder_need_instr2;
|
||||
logic decoder_is_undef;
|
||||
adr_src_t decoder_adr_src;
|
||||
|
||||
logic is_undef;
|
||||
logic pc_incr;
|
||||
@ -68,15 +72,6 @@ module control (
|
||||
|
||||
sp_src_t sp_src;
|
||||
|
||||
`define DEF_FF(register, next, we, rst_value) \
|
||||
always_ff @(posedge clk_i or negedge nreset_i) begin \
|
||||
if (~nreset_i) begin \
|
||||
register <= (rst_value); \
|
||||
end else if ((we)) begin \
|
||||
register <= (next); \
|
||||
end \
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i) begin
|
||||
nreset_r <= nreset_i;
|
||||
end
|
||||
@ -135,9 +130,10 @@ module control (
|
||||
.alu_op_valid_o(alu_op_valid_o),
|
||||
.alu_op_o (alu_op_o),
|
||||
.op_src_o (op_src_o),
|
||||
.op_dest_o (op_dest_o)
|
||||
|
||||
.op_dest_o (op_dest_o),
|
||||
|
||||
.reg16_dest_o (reg16_dest_o),
|
||||
.adr_src_o (decoder_adr_src)
|
||||
);
|
||||
|
||||
assign decoder_instr0_selected = (state_r == ST1_DEC) ? rdata_i : instr_r;
|
||||
@ -145,7 +141,7 @@ module control (
|
||||
assign decoder_instr2_selected = (state_r == ST3_DEC) ? rdata_i : operand1_r;
|
||||
|
||||
assign is_undef = (state_r != ST0_ADDR & decoder_is_undef);
|
||||
assign instr_valid = (state_r == ST4_EXEC);
|
||||
assign instr_valid = (state_r == ST2_EXEC | state_r == ST4_EXEC);
|
||||
|
||||
assign pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2);
|
||||
|
||||
@ -159,4 +155,7 @@ module control (
|
||||
assign operand8_o = operand0_r;
|
||||
assign operand16_o = {operand1_r, operand0_r};
|
||||
|
||||
assign adr_src_o = (state_r == ST2_EXEC) | (state_r == ST4_EXEC) ? decoder_adr_src :
|
||||
ADR_SRC_PC;
|
||||
|
||||
endmodule : control
|
||||
|
@ -25,6 +25,23 @@ module cpu (
|
||||
logic [15:0] pc;
|
||||
logic [15:0] sp;
|
||||
|
||||
logic instr_valid;
|
||||
logic instr_undef;
|
||||
|
||||
logic [ 7:0] operand8;
|
||||
logic [15:0] operand16;
|
||||
|
||||
reg8_t reg8_wselect;
|
||||
logic reg8_we;
|
||||
logic [ 7:0] reg8_wdata;
|
||||
reg16_t reg16_wselect;
|
||||
logic reg16_we;
|
||||
logic [15:0] reg16_wdata;
|
||||
reg8_t reg8_rselect;
|
||||
reg16_t reg16_rselect;
|
||||
logic [ 7:0] reg8_rdata;
|
||||
logic [15:0] reg16_rdata;
|
||||
|
||||
control control_inst (
|
||||
.clk_i (clk_i),
|
||||
.nreset_i (nreset_i),
|
||||
@ -35,7 +52,12 @@ module cpu (
|
||||
.alu_op_valid_o(alu_op_valid),
|
||||
.alu_op_o (alu_op),
|
||||
.op_src_o (op_src),
|
||||
.op_dest_o (op_dest)
|
||||
.op_dest_o (op_dest),
|
||||
.instr_valid_o (instr_valid),
|
||||
.instr_undef_o (instr_undef),
|
||||
.operand8_o (operand8),
|
||||
.operand16_o (operand16),
|
||||
.reg16_dest_o (reg16_wselect)
|
||||
);
|
||||
|
||||
alu alu_inst (
|
||||
@ -50,12 +72,31 @@ module cpu (
|
||||
|
||||
registers registers_inst (
|
||||
.clk_i (clk_i),
|
||||
.nreset_i(nreset_i)
|
||||
.nreset_i(nreset_i),
|
||||
|
||||
.reg8_wselect_i (reg8_wselect),
|
||||
.reg8_we_i (reg8_we),
|
||||
.reg8_wdata_i (reg8_wdata),
|
||||
.reg16_wselect_i(reg16_wselect),
|
||||
.reg16_we_i (reg16_we),
|
||||
.reg16_wdata_i (reg16_wdata),
|
||||
.reg8_rselect_i (reg8_rselect),
|
||||
.reg8_rdata_o (reg8_rdata),
|
||||
.reg16_rselect_i(reg16_rselect),
|
||||
.reg16_rdata_o (reg16_rdata)
|
||||
);
|
||||
|
||||
assign alu_operand = (op_src == OP_SRC_A) ? rega :
|
||||
'0;
|
||||
|
||||
assign reg8_wselect = reg8_t'('X);
|
||||
assign reg8_we = '0;
|
||||
assign reg8_wdata = operand8;
|
||||
assign reg16_we = instr_valid & (op_dest == OP_DEST_R16);
|
||||
assign reg16_wdata = operand16;
|
||||
assign reg8_rselect = reg8_t'('X);
|
||||
assign reg16_rselect = reg16_t'('X);
|
||||
|
||||
assign address_o = pc;
|
||||
|
||||
endmodule : cpu
|
||||
|
@ -22,6 +22,13 @@ package cpu_pkg;
|
||||
REG8_L = 3'h05
|
||||
} reg8_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
REG16_BC = 2'h00,
|
||||
REG16_DE = 2'h01,
|
||||
REG16_HL = 2'h02,
|
||||
REG16_SP_AF = 2'h03
|
||||
} reg16_t;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
ALU_OP_ADD = 3'h00,
|
||||
ALU_OP_ADC = 3'h01,
|
||||
@ -35,15 +42,31 @@ package cpu_pkg;
|
||||
|
||||
typedef enum {
|
||||
OP_SRC_A,
|
||||
OP_SRC_REG8
|
||||
OP_SRC_REG8,
|
||||
OP_SRC_OPERAND16
|
||||
} op_src_t;
|
||||
|
||||
typedef enum {
|
||||
OP_DEST_A
|
||||
OP_DEST_A,
|
||||
OP_DEST_R16
|
||||
} op_dest_t;
|
||||
|
||||
typedef enum {
|
||||
SP_SRC_OPERAND16
|
||||
} sp_src_t;
|
||||
|
||||
typedef enum {
|
||||
ADR_SRC_PC,
|
||||
ADR_SRC_HL
|
||||
} adr_src_t;
|
||||
|
||||
endpackage
|
||||
|
||||
`define DEF_FF(register, next, we, rst_value) \
|
||||
always_ff @(posedge clk_i or negedge nreset_i) begin \
|
||||
if (~nreset_i) begin \
|
||||
register <= (rst_value); \
|
||||
end else if ((we)) begin \
|
||||
register <= (next); \
|
||||
end \
|
||||
end
|
||||
|
@ -19,7 +19,11 @@ module decode (
|
||||
output logic alu_op_valid_o,
|
||||
output alu_op_t alu_op_o,
|
||||
output op_src_t op_src_o,
|
||||
output op_dest_t op_dest_o
|
||||
output op_dest_t op_dest_o,
|
||||
|
||||
output reg16_t reg16_dest_o,
|
||||
|
||||
output adr_src_t adr_src_o
|
||||
);
|
||||
|
||||
logic [1:0] dec_x;
|
||||
@ -38,21 +42,30 @@ module decode (
|
||||
assign dec_p = instr0_i[5:4];
|
||||
assign dec_q = instr0_i[3];
|
||||
|
||||
assign is_ld_rr_nnnn = (dec_z == 3'h1) & ~dec_q & (dec_p != 2'h3);
|
||||
assign is_ld_sp_nnnn = (dec_z == 3'h1) & ~dec_q & (dec_p == 2'h3);
|
||||
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_alu_a_n = (dec_x == 3'h2);
|
||||
|
||||
assign need_instr1_o = is_ld_sp_nnnn;
|
||||
assign need_instr2_o = is_ld_sp_nnnn;
|
||||
|
||||
assign undef_o = ~(is_ld_sp_nnnn | is_alu_a_n);
|
||||
assign undef_o = ~(is_ld_sp_nnnn | is_ld_rr_nnnn | is_alu_a_n);
|
||||
|
||||
assign sp_we_o = is_ld_sp_nnnn & (state_i == ST4_EXEC);
|
||||
|
||||
assign alu_op_valid_o = is_alu_a_n;
|
||||
assign alu_op_o = alu_op_t'(dec_y);
|
||||
assign op_dest_o = is_alu_a_n ? OP_DEST_A : op_dest_t'('X);
|
||||
assign op_src_o = is_alu_a_n ? OP_SRC_REG8 : op_src_t'('X);
|
||||
assign op_dest_o = is_alu_a_n ? OP_DEST_A :
|
||||
is_ld_rr_nnnn ? OP_DEST_R16 :
|
||||
op_dest_t'('X);
|
||||
|
||||
assign op_src_o = is_alu_a_n ? OP_SRC_REG8 :
|
||||
is_ld_rr_nnnn ? OP_SRC_OPERAND16 :
|
||||
op_src_t'('X);
|
||||
|
||||
assign reg16_dest_o = reg16_t'(dec_p);
|
||||
|
||||
assign adr_src_o = ADR_SRC_PC;
|
||||
|
||||
endmodule : decode
|
@ -1,6 +1,49 @@
|
||||
`include "cpu_pkg.svh"
|
||||
|
||||
import cpu_pkg::*;
|
||||
|
||||
module registers (
|
||||
input logic clk_i,
|
||||
input logic nreset_i
|
||||
input logic nreset_i,
|
||||
|
||||
input reg8_t reg8_wselect_i,
|
||||
input logic reg8_we_i,
|
||||
input logic [ 7:0] reg8_wdata_i,
|
||||
|
||||
input reg16_t reg16_wselect_i,
|
||||
input logic reg16_we_i,
|
||||
input logic [15:0] reg16_wdata_i,
|
||||
|
||||
input reg8_t reg8_rselect_i,
|
||||
input reg16_t reg16_rselect_i,
|
||||
output logic [ 7:0] reg8_rdata_o,
|
||||
output logic [15:0] reg16_rdata_o
|
||||
);
|
||||
|
||||
logic [15:0] reg_r [0:2];
|
||||
logic [15:0] reg_next;
|
||||
logic [ 1:0] reg_we [0:2];
|
||||
|
||||
generate for (genvar i = 0; i <= 2; i++) begin : gen_regs
|
||||
always_ff @(posedge clk_i or negedge nreset_i) begin
|
||||
if (~nreset_i) begin
|
||||
reg_r[i] <= '0;
|
||||
end else if (|reg_we[i]) begin
|
||||
reg_r[i]<= reg_next;
|
||||
end
|
||||
end
|
||||
|
||||
assign reg_we[i][0] = (reg16_we_i & (reg16_wselect_i == i)) |
|
||||
(reg8_we_i & ({reg8_wselect_i, 1'b0} == i));
|
||||
assign reg_we[i][1] = (reg16_we_i & (reg16_wselect_i == i)) |
|
||||
(reg8_we_i & ({reg8_wselect_i, 1'b1} == i));
|
||||
end endgenerate
|
||||
|
||||
assign reg_next = ({16{reg8_we_i}} & {reg8_wdata_i, reg8_wdata_i}) |
|
||||
({16{reg16_we_i}} & reg16_wdata_i);
|
||||
|
||||
assign reg8_rdata_o = reg8_rselect_i[0] ? reg_r[reg8_rselect_i[2:1]][15:8] :
|
||||
reg_r[reg8_rselect_i[2:1]][ 7:0];
|
||||
assign reg16_rdata_o = reg_r[reg16_rselect_i];
|
||||
|
||||
endmodule : registers
|
||||
|
@ -13,5 +13,20 @@ module tb_top ();
|
||||
.nreset_i(nreset)
|
||||
);
|
||||
|
||||
// Testbench code
|
||||
logic instr_undef;
|
||||
logic [15:0] last_pc;
|
||||
logic [ 7:0] last_opcode;
|
||||
|
||||
assign instr_undef = gb_inst.cpu_inst.control_inst.is_undef;
|
||||
assign last_pc = gb_inst.cpu_inst.control_inst.instr_pc_r;
|
||||
assign last_opcode = gb_inst.cpu_inst.control_inst.instr_r;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (nreset && instr_undef) begin
|
||||
$info($sformatf("[%t] %X: Undefined opcode %X", $time(), last_pc, last_opcode));
|
||||
$fatal(0);
|
||||
end
|
||||
end
|
||||
|
||||
endmodule : tb_top
|
||||
|
Loading…
Reference in New Issue
Block a user