From 237a5f148915fdaea3f960c0792b75e450eab7cf Mon Sep 17 00:00:00 2001 From: Koray Yanik Date: Tue, 16 Feb 2021 23:05:46 +0000 Subject: [PATCH] Implemented SP, $nnnn and XOR A instructions --- build/tb_top.Makefile | 5 ++-- rtl/cpu/alu.sv | 54 ++++++++++++++++++++++++++++++++++++++++++ rtl/cpu/control.sv | 32 +++++++++++++++++++++++-- rtl/cpu/cpu.sv | 41 +++++++++++++++++++++++++++----- rtl/cpu/cpu_pkg.svh | 38 +++++++++++++++++++++++++++++- rtl/cpu/decode.sv | 55 ++++++++++++++++++++++++++++++++++++------- 6 files changed, 205 insertions(+), 20 deletions(-) create mode 100644 rtl/cpu/alu.sv diff --git a/build/tb_top.Makefile b/build/tb_top.Makefile index 718e373..325ea7c 100644 --- a/build/tb_top.Makefile +++ b/build/tb_top.Makefile @@ -1,8 +1,9 @@ TB = tb_top -SOURCES = gb.sv cpu.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 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 fetch.sdb registers.sdb +cpu.sdb: control.sdb registers.sdb alu.sdb +control.sdb: decode.sdb include ../synthflow/vivado/Makefile.rules \ No newline at end of file diff --git a/rtl/cpu/alu.sv b/rtl/cpu/alu.sv new file mode 100644 index 0000000..18901a4 --- /dev/null +++ b/rtl/cpu/alu.sv @@ -0,0 +1,54 @@ +`include "cpu_pkg.svh" + +import cpu_pkg::*; + +module alu ( + input logic clk_i, + input logic nreset_i, + + input logic alu_op_valid_i, + input alu_op_t alu_op_i, + input logic [7:0] operand_i, + + output logic [ 7:0] a_o, + output logic [ 7:0] f_o +); + + logic a_we; + logic [ 7:0] a_r; + logic [ 7:0] a_next; + + logic f_we; + logic [ 7:0] f_r; + logic [ 7:0] f_next; + + 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); + + assign a_we = alu_op_valid_i; + assign a_next = (alu_op_i == ALU_OP_XOR) ? a_xor : + a_xor; + + assign f_we = alu_op_valid_i; + assign f_next = (alu_op_i == ALU_OP_XOR) ? f_xor : + f_xor; + + assign a_xor = (a_r ^ operand_i); + assign f_xor = {~(|a_xor), 3'b0, f_r[3:0]}; + + assign a_o = a_r; + assign f_o = f_r; + +endmodule : alu \ No newline at end of file diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv index 87406e1..59f9189 100644 --- a/rtl/cpu/control.sv +++ b/rtl/cpu/control.sv @@ -11,11 +11,17 @@ module control ( output state_t state_o, output logic [15:0] pc_o, + output logic [15:0] sp_o, output logic instr_valid_o, output logic instr_undef_o, output logic [ 7:0] operand8_o, - output logic [15:0] operand16_o + output logic [15:0] operand16_o, + + 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 ); logic nreset_r; @@ -29,6 +35,10 @@ module control ( logic [15:0] pc_next; + logic sp_we; + logic [15:0] sp_r; + logic [15:0] sp_next; + logic instr_pc_we; logic [15:0] instr_pc_r; logic [15:0] instr_pc_next; @@ -56,6 +66,8 @@ module control ( logic pc_incr; logic instr_valid; + 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 \ @@ -71,6 +83,7 @@ module control ( `DEF_FF(state_r, state_next, state_we, ST0_ADDR); `DEF_FF(pc_r, pc_next, pc_we, '0); + `DEF_FF(sp_r, sp_next, sp_we, '0); `DEF_FF(instr_pc_r, instr_pc_next, instr_pc_we, '0); `DEF_FF(instr_r, instr_next, instr_we, '0); `DEF_FF(operand0_r, operand0_next, operand0_we, '0); @@ -79,6 +92,8 @@ module control ( assign pc_we = nreset_r & pc_incr & ~is_undef; assign pc_next = (pc_r + 16'b1); + assign sp_next = (sp_src == SP_SRC_OPERAND16) ? {operand1_r, operand0_r} : '0; + assign instr_we = (state_r == ST1_DEC); assign instr_next = rdata_i; @@ -108,9 +123,21 @@ module control ( .instr0_i (decoder_instr0_selected), .instr1_i (decoder_instr1_selected), .instr2_i (decoder_instr2_selected), + .state_i (state_r), + .need_instr1_o(decoder_need_instr1), .need_instr2_o(decoder_need_instr2), - .undef_o (decoder_is_undef) + .undef_o (decoder_is_undef), + + .sp_we_o (sp_we), + .sp_src_o (sp_src), + + .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) + + ); assign decoder_instr0_selected = (state_r == ST1_DEC) ? rdata_i : instr_r; @@ -124,6 +151,7 @@ module control ( assign state_o = state_r; assign pc_o = pc_r; + assign sp_o = sp_r; assign instr_valid_o = instr_valid; assign instr_undef_o = is_undef; diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv index 60e8fad..fdcc0e8 100644 --- a/rtl/cpu/cpu.sv +++ b/rtl/cpu/cpu.sv @@ -10,16 +10,42 @@ module cpu ( input logic [ 7:0] rdata_i ); - state_t state; + state_t state; + + logic alu_op_valid; + alu_op_t alu_op; + op_src_t op_src; + op_dest_t op_dest; + + logic [ 7:0] alu_operand; + + logic [ 7:0] rega; + logic [ 7:0] regf; logic [15:0] pc; + logic [15:0] sp; control control_inst ( - .clk_i (clk_i), - .nreset_i(nreset_i), - .rdata_i (rdata_i), - .state_o (state), - .pc_o (pc) + .clk_i (clk_i), + .nreset_i (nreset_i), + .rdata_i (rdata_i), + .state_o (state), + .pc_o (pc), + .sp_o (sp), + .alu_op_valid_o(alu_op_valid), + .alu_op_o (alu_op), + .op_src_o (op_src), + .op_dest_o (op_dest) + ); + + alu alu_inst ( + .clk_i (clk_i), + .nreset_i (nreset_i), + .alu_op_valid_i(alu_op_valid), + .alu_op_i (alu_op), + .operand_i (alu_operand), + .a_o (rega), + .f_o (regf) ); registers registers_inst ( @@ -27,6 +53,9 @@ module cpu ( .nreset_i(nreset_i) ); + assign alu_operand = (op_src == OP_SRC_A) ? rega : + '0; + assign address_o = pc; endmodule : cpu diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh index 3e2eef7..db29164 100644 --- a/rtl/cpu/cpu_pkg.svh +++ b/rtl/cpu/cpu_pkg.svh @@ -1,13 +1,49 @@ package cpu_pkg; + // + // 4 | ST0_ADDR -> ST1_DEC -> ST2_EXEC -> ST3_NOP + // 12 | '-> ST2_DEC -> ST3_DEC -> ST4_EXEC -> .... -> ST11_NOP + // typedef enum { ST0_ADDR, ST1_DEC, ST2_EXEC, ST2_DEC, - ST3_INC_ADDR, ST3_DEC, ST4_EXEC } state_t; + typedef enum logic [2:0] { + REG8_B = 3'h00, + REG8_C = 3'h01, + REG8_D = 3'h02, + REG8_E = 3'h03, + REG8_H = 3'h04, + REG8_L = 3'h05 + } reg8_t; + + typedef enum logic [2:0] { + ALU_OP_ADD = 3'h00, + ALU_OP_ADC = 3'h01, + ALU_OP_SUB = 3'h02, + ALU_OP_SBC = 3'h03, + ALU_OP_AND = 3'h04, + ALU_OP_XOR = 3'h05, + ALU_OP_OR = 3'h06, + ALU_OP_CP = 3'h07 + } alu_op_t; + + typedef enum { + OP_SRC_A, + OP_SRC_REG8 + } op_src_t; + + typedef enum { + OP_DEST_A + } op_dest_t; + + typedef enum { + SP_SRC_OPERAND16 + } sp_src_t; + endpackage diff --git a/rtl/cpu/decode.sv b/rtl/cpu/decode.sv index c0b5d41..ead796b 100644 --- a/rtl/cpu/decode.sv +++ b/rtl/cpu/decode.sv @@ -1,21 +1,58 @@ -module decode ( - input [7:0] instr0_i, - input [7:0] instr1_i, - input [7:0] instr2_i, +`include "cpu_pkg.svh" - output logic need_instr1_o, - output logic need_instr2_o, - output logic undef_o +import cpu_pkg::*; + +module decode ( + input logic [7:0] instr0_i, + input logic [7:0] instr1_i, + input logic [7:0] instr2_i, + + input state_t state_i, + + output logic need_instr1_o, + output logic need_instr2_o, + output logic undef_o, + + output logic sp_we_o, + output sp_src_t sp_src_o, + + 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 ); + logic [1:0] dec_x; + logic [2:0] dec_y; + logic [2:0] dec_z; + logic [1:0] dec_p; + logic dec_q; + + logic is_ld_rr_nnnn; logic is_ld_sp_nnnn; + logic is_alu_a_n; + assign dec_x = instr0_i[7:6]; + assign dec_y = instr0_i[5:3]; + assign dec_z = instr0_i[2:0]; + assign dec_p = instr0_i[5:4]; + assign dec_q = instr0_i[3]; - assign is_ld_sp_nnnn = (instr0_i == 7'h31); + 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_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; + assign undef_o = ~(is_ld_sp_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); endmodule : decode \ No newline at end of file