From e713f8de87085ced00ed7cc9367a71a913782b1a Mon Sep 17 00:00:00 2001 From: Koray Yanik Date: Tue, 8 Feb 2022 23:53:02 +0000 Subject: [PATCH] Implement RLA and POP RR --- build/tb_top.Makefile | 2 +- rtl/cpu/alu.sv | 3 ++- rtl/cpu/control.sv | 6 ++++-- rtl/cpu/cpu.sv | 5 +++++ rtl/cpu/cpu_pkg.svh | 9 ++++++--- rtl/cpu/decode.sv | 34 +++++++++++++++++++++++++++------- rtl/gb.sv | 26 +++++++++++++++++++++++++- rtl/shared/ram.sv | 34 ++++++++++++++++++++++++++++++++++ rtl/shared/rom.sv | 7 ++++++- 9 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 rtl/shared/ram.sv diff --git a/build/tb_top.Makefile b/build/tb_top.Makefile index 2495f61..b7290f0 100644 --- a/build/tb_top.Makefile +++ b/build/tb_top.Makefile @@ -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 diff --git a/rtl/cpu/alu.sv b/rtl/cpu/alu.sv index e42106c..1793bf7 100644 --- a/rtl/cpu/alu.sv +++ b/rtl/cpu/alu.sv @@ -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 : diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv index fd6a088..1414413 100644 --- a/rtl/cpu/control.sv +++ b/rtl/cpu/control.sv @@ -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), diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv index 1e0e627..602f27b 100644 --- a/rtl/cpu/cpu.sv +++ b/rtl/cpu/cpu.sv @@ -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} : diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh index b89291a..25c7517 100644 --- a/rtl/cpu/cpu_pkg.svh +++ b/rtl/cpu/cpu_pkg.svh @@ -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 diff --git a/rtl/cpu/decode.sv b/rtl/cpu/decode.sv index 472183a..32d2b0f 100644 --- a/rtl/cpu/decode.sv +++ b/rtl/cpu/decode.sv @@ -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; diff --git a/rtl/gb.sv b/rtl/gb.sv index 18e2e3d..ef34564 100644 --- a/rtl/gb.sv +++ b/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 diff --git a/rtl/shared/ram.sv b/rtl/shared/ram.sv new file mode 100644 index 0000000..a105c69 --- /dev/null +++ b/rtl/shared/ram.sv @@ -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 diff --git a/rtl/shared/rom.sv b/rtl/shared/rom.sv index 9986ba5..2a9b460 100644 --- a/rtl/shared/rom.sv +++ b/rtl/shared/rom.sv @@ -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");