Implement RLA and POP RR
This commit is contained in:
parent
4f892eb3f2
commit
e713f8de87
@ -1,5 +1,5 @@
|
||||
TB = tb_top
|
||||
SOURCES = gb.sv cpu.sv alu.sv registers.sv control.sv decode.sv rom.sv tb_top.sv clkgen.sv
|
||||
SOURCES = gb.sv cpu.sv alu.sv registers.sv control.sv decode.sv rom.sv ram.sv tb_top.sv clkgen.sv
|
||||
INCLUDES = cpu_pkg.svh
|
||||
PATH_SRC = ../rtl:../rtl/cpu:../rtl/shared:../sim/tbench:../sim/shared
|
||||
|
||||
|
@ -59,7 +59,8 @@ module alu (
|
||||
assign a_next = (alu_op_valid_i & (alu_op_i == ALU_OP_XOR)) ? a_xor :
|
||||
(alu_op_valid_i & (alu_op_i == ALU_OP_NOP)) ? operand_i :
|
||||
(alu_op_valid_i & (alu_op_i == ALU_OP_INC)) ? a_inc :
|
||||
a_r;
|
||||
(alu_op_valid_i & (alu_op_i == ALU_OP_ROT) & (rot_op_i == ROT_OP_RL)) ? out8_rl :
|
||||
a_r;
|
||||
|
||||
assign f_we = alu_op_valid_i | rot_op_valid_i;
|
||||
assign f_next = (alu_op_valid_i & (alu_op_i == ALU_OP_XOR)) ? f_xor :
|
||||
|
@ -75,6 +75,7 @@ module control (
|
||||
logic decoder_need_instr1;
|
||||
logic decoder_need_instr2;
|
||||
logic decoder_is_multicycle;
|
||||
logic decoder_is_multicycle2;
|
||||
logic decoder_is_undef;
|
||||
logic decoder_alu_op_valid;
|
||||
logic decoder_rot_op_valid;
|
||||
@ -144,8 +145,8 @@ module control (
|
||||
|
||||
ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST3_EXEC;
|
||||
ST3_DEC: state_next = ST4_EXEC;
|
||||
ST3_EXEC: state_next = ST0_ADDR;
|
||||
ST4_EXEC: state_next = decoder_is_multicycle ? ST5_EXEC : ST0_ADDR;
|
||||
ST3_EXEC: state_next = decoder_is_multicycle2 ? ST4_EXEC : ST0_ADDR;
|
||||
ST4_EXEC: state_next = decoder_need_instr2 & decoder_is_multicycle ? ST5_EXEC : ST0_ADDR;
|
||||
ST5_EXEC: state_next = ST0_ADDR;
|
||||
endcase
|
||||
end
|
||||
@ -159,6 +160,7 @@ module control (
|
||||
.need_instr1_o (decoder_need_instr1),
|
||||
.need_instr2_o (decoder_need_instr2),
|
||||
.is_multicycle_o(decoder_is_multicycle),
|
||||
.is_multicycle2_o(decoder_is_multicycle2),
|
||||
.undef_o (decoder_is_undef),
|
||||
|
||||
.sp_we_o (decoder_sp_we),
|
||||
|
@ -32,6 +32,8 @@ module cpu (
|
||||
logic [15:0] sp;
|
||||
logic [15:0] hl;
|
||||
|
||||
logic [15:0] sp_p1;
|
||||
|
||||
logic instr_valid;
|
||||
logic instr_undef;
|
||||
|
||||
@ -119,6 +121,8 @@ module cpu (
|
||||
.hl_o (hl)
|
||||
);
|
||||
|
||||
assign sp_p1 = (sp + 16'h01);
|
||||
|
||||
assign alu_operand = (op_src == OP_SRC_A) ? rega :
|
||||
(op_src == OP_SRC_F) ? regf :
|
||||
(op_src == OP_SRC_OPERAND8) ? operand8 :
|
||||
@ -136,6 +140,7 @@ module cpu (
|
||||
|
||||
assign address_o = (adr_src == ADR_SRC_HL) ? hl :
|
||||
(adr_src == ADR_SRC_SP) ? sp :
|
||||
(adr_src == ADR_SRC_SP_P1) ? sp_p1 :
|
||||
(adr_src == ADR_SRC_REG8) ? {8'hFF, reg8_rdata} :
|
||||
(adr_src == ADR_SRC_REG16) ? reg16_rdata :
|
||||
(adr_src == ADR_SRC_OPERAND8) ? {8'hFF, operand8} :
|
||||
|
@ -50,9 +50,11 @@ package cpu_pkg;
|
||||
ALU_OP_OR = 5'h06,
|
||||
ALU_OP_CP = 5'h07,
|
||||
ALU_OP_BIT = 5'h08,
|
||||
ALU_OP_NOP = 5'h09,
|
||||
ALU_OP_INC = 5'h10,
|
||||
ALU_OP_INCR = 5'h11 // Increment register instead of a
|
||||
ALU_OP_NOP = 5'h09, // Write operand to a
|
||||
ALU_OP_NOPF = 5'h0a, // Write operand to f
|
||||
ALU_OP_ROT = 5'h0b,
|
||||
ALU_OP_INC = 5'h0c,
|
||||
ALU_OP_INCR = 5'h0d // Increment register instead of a
|
||||
} alu_op_t;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
@ -101,6 +103,7 @@ package cpu_pkg;
|
||||
ADR_SRC_PC,
|
||||
ADR_SRC_HL,
|
||||
ADR_SRC_SP,
|
||||
ADR_SRC_SP_P1, // SP + 1 for pop
|
||||
ADR_SRC_REG8, // extended with FF
|
||||
ADR_SRC_REG16,
|
||||
ADR_SRC_OPERAND8, // extended with FF
|
||||
|
@ -12,6 +12,7 @@ module decode (
|
||||
output logic need_instr1_o,
|
||||
output logic need_instr2_o,
|
||||
output logic is_multicycle_o,
|
||||
output logic is_multicycle2_o,
|
||||
output logic undef_o,
|
||||
|
||||
output logic sp_we_o,
|
||||
@ -61,11 +62,13 @@ module decode (
|
||||
logic is_alu_a_r;
|
||||
logic is_bit_n_r;
|
||||
logic is_rot_r;
|
||||
logic is_rla;
|
||||
logic is_inc_a;
|
||||
logic is_inc_r;
|
||||
logic is_jr_cc_n;
|
||||
logic is_call_nn;
|
||||
logic is_push_rr;
|
||||
logic is_pop_rr;
|
||||
|
||||
reg8_t reg8_dest;
|
||||
reg8_t reg8_src;
|
||||
@ -96,12 +99,15 @@ module decode (
|
||||
assign is_bit_n_r = (is_cb & instr1_i[7:6] == 2'h1);
|
||||
assign is_rot_r = (is_cb & instr1_i[7:6] == 2'h0);
|
||||
|
||||
assign is_rla = (dec_x == 3'h0) & (dec_z == 3'h7) & (dec_y == 3'h2);
|
||||
|
||||
assign is_inc_a = is_inc_r & (reg8_dest == REG8_A);
|
||||
assign is_inc_r = (dec_x == 2'h0) & (dec_z == 3'h4);
|
||||
|
||||
assign is_jr_cc_n = (dec_x == 2'h0) & (dec_z == 2'h0) & dec_y[2];
|
||||
assign is_call_nn = (instr0_i == 8'hCD);
|
||||
assign is_push_rr = (dec_x == 2'h3) & (dec_z == 3'h5) && ~dec_q;
|
||||
assign is_push_rr = (dec_x == 2'h3) & (dec_z == 3'h5) & ~dec_q;
|
||||
assign is_pop_rr = (dec_x == 2'h3) & (dec_z == 3'h1) & ~dec_q;
|
||||
|
||||
assign reg8_src = is_cb ? reg8_t'(instr1_i[2:0]) :
|
||||
is_ldh_c_a ? REG8_C :
|
||||
@ -110,36 +116,44 @@ module decode (
|
||||
(is_push_rr & state_i == ST3_EXEC) ? reg8_t'({dec_p, 1'b1}) :
|
||||
reg8_t'(dec_z);
|
||||
assign reg8_dest = is_rot_r ? reg8_t'(dec_z) :
|
||||
(is_pop_rr & state_i == ST3_EXEC) ? reg8_t'({dec_p, 1'b1}) :
|
||||
(is_pop_rr & state_i == ST4_EXEC) ? reg8_t'({dec_p, 1'b0}) :
|
||||
reg8_t'(dec_y);
|
||||
|
||||
assign reg16_src = is_ldd_hl_a ? REG16_HL : reg16_t'(dec_p);
|
||||
|
||||
assign need_instr1_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn | is_call_nn | is_cb | is_jr_cc_n | is_ld_r_n | is_ldh_n_a;
|
||||
assign need_instr2_o = is_ld_sp_nn | is_ld_rr_nn | is_ld_a_nn | is_call_nn;
|
||||
assign is_multicycle_o = is_ld_a_rr | is_call_nn | is_push_rr;
|
||||
assign is_multicycle_o = is_ld_a_rr | is_call_nn | is_push_rr | is_pop_rr;
|
||||
assign is_multicycle2_o = is_pop_rr;
|
||||
|
||||
assign undef_o = ~(is_ldh_n_a | is_ld_r_r | is_ld_sp_nn | is_ld_rr_nn | is_alu_a_r | is_ldd_hl_a | is_bit_n_r |
|
||||
is_jr_cc_n | is_ld_r_n | is_ldh_c_a | is_inc_r | is_ld_rr_a | is_ld_a_rr | is_call_nn |
|
||||
is_push_rr | (is_rot_r & (instr1_i[5:3] == 3'h02)));
|
||||
is_push_rr | is_pop_rr | (is_rot_r & (instr1_i[5:3] == 3'h02)) | is_rla);
|
||||
|
||||
assign sp_we_o = is_ld_sp_nn | is_call_nn | is_push_rr;
|
||||
assign sp_we_o = is_ld_sp_nn | is_call_nn | is_push_rr | (is_pop_rr & ((state_i == ST2_EXEC) | (state_i == ST3_EXEC)));
|
||||
assign sp_src_o = is_ld_sp_nn ? SP_SRC_OPERAND16 :
|
||||
is_call_nn ? SP_SRC_DEC :
|
||||
is_push_rr ? SP_SRC_DEC :
|
||||
is_pop_rr ? SP_SRC_INC :
|
||||
sp_src_t'('X);
|
||||
|
||||
assign alu_op_valid_o = is_alu_a_r | is_bit_n_r | is_ld_a_n | is_ld_a_rr | is_ld_a_nn | is_inc_r;
|
||||
assign alu_op_valid_o = is_alu_a_r | is_bit_n_r | is_ld_a_n | is_ld_a_rr | is_ld_a_nn | is_inc_r | is_rla | (is_pop_rr & reg16_src == REG16_SP_AF);
|
||||
assign alu_op_o = is_bit_n_r ? ALU_OP_BIT :
|
||||
is_ld_a_n ? ALU_OP_NOP :
|
||||
is_ld_a_nn ? ALU_OP_NOP :
|
||||
is_ld_a_rr ? ALU_OP_NOP :
|
||||
is_inc_a ? ALU_OP_INC :
|
||||
is_inc_r ? ALU_OP_INCR :
|
||||
is_rla ? ALU_OP_ROT :
|
||||
(is_pop_rr & reg16_src == REG16_SP_AF & state_i == ST2_EXEC) ? ALU_OP_NOP :
|
||||
(is_pop_rr & reg16_src == REG16_SP_AF & state_i == ST3_EXEC) ? ALU_OP_NOPF :
|
||||
alu_op_t'({1'b0, dec_y});
|
||||
assign reg_write_alu_o = is_inc_r | is_rot_r;
|
||||
|
||||
assign rot_op_valid_o = is_rot_r;
|
||||
assign rot_op_o = rot_op_t'(instr1_i[5:3]);
|
||||
assign rot_op_valid_o = is_rot_r | is_rla;
|
||||
assign rot_op_o = is_rla ? ROT_OP_RL :
|
||||
rot_op_t'(instr1_i[5:3]);
|
||||
|
||||
assign op_dest_o = (is_ld_r_r & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY :
|
||||
(is_ld_r_n & reg8_dest == REG8_PHL) ? OP_DEST_MEMORY :
|
||||
@ -157,7 +171,10 @@ module decode (
|
||||
is_inc_r ? OP_DEST_REG8 :
|
||||
is_call_nn ? OP_DEST_MEMORY :
|
||||
is_push_rr ? OP_DEST_MEMORY :
|
||||
(is_pop_rr & reg16_src != REG16_SP_AF) ? OP_DEST_REG8 :
|
||||
(is_pop_rr & reg16_src == REG16_SP_AF) ? OP_DEST_A :
|
||||
is_rot_r ? OP_DEST_REG8 :
|
||||
is_rla ? OP_DEST_A :
|
||||
op_dest_t'('X);
|
||||
|
||||
assign op_src_o = (is_ld_r_r & reg8_src == REG8_A) ? OP_SRC_A :
|
||||
@ -174,11 +191,13 @@ module decode (
|
||||
is_ldd_hl_a ? OP_SRC_REG16 :
|
||||
is_bit_n_r ? OP_SRC_REG8 :
|
||||
is_rot_r ? OP_SRC_REG8 :
|
||||
is_rla ? OP_SRC_A :
|
||||
(is_call_nn & state_i == ST4_EXEC) ? OP_SRC_PC_L :
|
||||
(is_call_nn & state_i == ST5_EXEC) ? OP_SRC_PC_H :
|
||||
(is_push_rr & reg16_src != REG16_SP_AF) ? OP_SRC_REG8 :
|
||||
(is_push_rr & reg16_src == REG16_SP_AF & state_i == ST2_EXEC) ? OP_SRC_A :
|
||||
(is_push_rr & reg16_src == REG16_SP_AF & state_i == ST3_EXEC) ? OP_SRC_F :
|
||||
is_pop_rr ? OP_SRC_MEMORY :
|
||||
op_src_t'('X);
|
||||
|
||||
assign reg8_dest_o = reg8_dest;
|
||||
@ -202,6 +221,7 @@ module decode (
|
||||
is_ld_rr_a ? ADR_SRC_REG16 :
|
||||
is_call_nn ? ADR_SRC_SP :
|
||||
is_push_rr ? ADR_SRC_SP :
|
||||
is_pop_rr ? ADR_SRC_SP_P1 :
|
||||
ADR_SRC_PC;
|
||||
|
||||
assign branch_always_o = is_call_nn;
|
||||
|
26
rtl/gb.sv
26
rtl/gb.sv
@ -8,6 +8,12 @@ module gb (
|
||||
logic [ 7:0] rdata;
|
||||
logic [ 7:0] wdata;
|
||||
|
||||
logic rom_cs;
|
||||
logic [ 7:0] rom_rdata;
|
||||
|
||||
logic hi_ram_cs;
|
||||
logic [ 7:0] hi_ram_rdata;
|
||||
|
||||
cpu cpu_inst (
|
||||
.clk_i (clk_i),
|
||||
.nreset_i (nreset_i),
|
||||
@ -23,8 +29,26 @@ module gb (
|
||||
.DATA_W (8)
|
||||
) rom_inst (
|
||||
.clk_i (clk_i),
|
||||
.cs_i (rom_cs),
|
||||
.address_i(address[7:0]),
|
||||
.rdata_o (rdata)
|
||||
.rdata_o (rom_rdata)
|
||||
);
|
||||
|
||||
ram #(
|
||||
.ADDR_W (7),
|
||||
.DATA_W (8)
|
||||
) hi_ram_inst (
|
||||
.clk_i (clk_i),
|
||||
.cs_i (hi_ram_cs),
|
||||
.address_i (address[6:0]),
|
||||
.rdata_o (hi_ram_rdata),
|
||||
.we_i (we),
|
||||
.wdata_i (wdata)
|
||||
);
|
||||
|
||||
assign rom_cs = ~(|address[15:8]);
|
||||
assign hi_ram_cs = (&address[15:7]) & ~(&address[6:0]);
|
||||
|
||||
assign rdata = rom_rdata | hi_ram_rdata;
|
||||
|
||||
endmodule : gb
|
||||
|
34
rtl/shared/ram.sv
Normal file
34
rtl/shared/ram.sv
Normal file
@ -0,0 +1,34 @@
|
||||
module ram #(
|
||||
parameter DATA_W = 8,
|
||||
parameter ADDR_W = 8
|
||||
)(
|
||||
input logic clk_i,
|
||||
|
||||
input logic cs_i,
|
||||
|
||||
input logic [ADDR_W-1:0] address_i,
|
||||
input logic we_i,
|
||||
input logic [DATA_W-1:0] wdata_i,
|
||||
output logic [DATA_W-1:0] rdata_o
|
||||
);
|
||||
|
||||
localparam RAM_SIZE = 2**ADDR_W;
|
||||
|
||||
logic [DATA_W-1:0] ram [RAM_SIZE-1:0];
|
||||
|
||||
logic wenable;
|
||||
logic [DATA_W-1:0] rdata;
|
||||
|
||||
assign wenable = cs_i & we_i;
|
||||
|
||||
always_ff @(posedge clk_i)
|
||||
if (wenable)
|
||||
ram[address_i] <= wdata_i;
|
||||
|
||||
always_ff @(posedge clk_i)
|
||||
if (cs_i)
|
||||
rdata <= ram[address_i];
|
||||
|
||||
assign rdata_o = {DATA_W{cs_i}} & rdata;
|
||||
|
||||
endmodule
|
@ -4,6 +4,7 @@ module rom #(
|
||||
parameter integer unsigned DATA_W = 8
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic cs_i,
|
||||
input logic [ADDR_W-1:0] address_i,
|
||||
|
||||
output logic [DATA_W-1:0] rdata_o
|
||||
@ -12,9 +13,13 @@ module rom #(
|
||||
localparam ROM_SIZE = 2**ADDR_W;
|
||||
|
||||
logic [DATA_W-1:0] rom [ROM_SIZE-1:0];
|
||||
logic [DATA_W-1:0] rdata;
|
||||
|
||||
always_ff @(posedge clk_i)
|
||||
rdata_o <= rom[address_i];
|
||||
if (cs_i)
|
||||
rdata <= rom[address_i];
|
||||
|
||||
assign rdata_o = {DATA_W{cs_i}} & rdata;
|
||||
|
||||
initial begin
|
||||
static integer fd = $fopen(FILE_NAME, "rb");
|
||||
|
Loading…
Reference in New Issue
Block a user