From aa92344d10d02cdc43570aa3cc919472266d8219 Mon Sep 17 00:00:00 2001 From: Koray Yanik Date: Tue, 16 Feb 2021 21:13:50 +0000 Subject: [PATCH] Initial work on decoder Decode the LD SP, $nnnn instruction as our first three-byte instruction. --- .gitignore | 1 + build/tb_top.Makefile | 2 +- rtl/cpu/control.sv | 117 ++++++++++++++++++++++++++++++++++++------ rtl/cpu/cpu.sv | 1 + rtl/cpu/cpu_pkg.svh | 5 +- rtl/cpu/decode.sv | 21 ++++++++ sim/shared/clkgen.sv | 2 +- 7 files changed, 130 insertions(+), 19 deletions(-) create mode 100644 rtl/cpu/decode.sv diff --git a/.gitignore b/.gitignore index d9ca403..ec05609 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/.Xil build/xsim.dir +build/*.wcfg diff --git a/build/tb_top.Makefile b/build/tb_top.Makefile index 480d731..718e373 100644 --- a/build/tb_top.Makefile +++ b/build/tb_top.Makefile @@ -1,5 +1,5 @@ TB = tb_top -SOURCES = gb.sv cpu.sv registers.sv control.sv rom.sv tb_top.sv clkgen.sv +SOURCES = gb.sv cpu.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 diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv index b043132..87406e1 100644 --- a/rtl/cpu/control.sv +++ b/rtl/cpu/control.sv @@ -5,11 +5,22 @@ import cpu_pkg::*; module control ( input logic clk_i, input logic nreset_i, + + input logic [ 7:0] rdata_i, + output state_t state_o, - output logic [15:0] pc_o + output logic [15:0] pc_o, + + output logic instr_valid_o, + output logic instr_undef_o, + output logic [ 7:0] operand8_o, + output logic [15:0] operand16_o ); + logic nreset_r; + + logic state_we; state_t state_r; state_t state_next; @@ -17,33 +28,107 @@ module control ( logic [15:0] pc_r; logic [15:0] pc_next; - always_ff @(posedge clk_i or negedge nreset_i) begin - if (~nreset_i) - state_r <= ST0_ADDR; - else - state_r <= state_next; + + logic instr_pc_we; + logic [15:0] instr_pc_r; + logic [15:0] instr_pc_next; + + logic instr_we; + logic [ 7:0] instr_r; + logic [ 7:0] instr_next; + + logic operand0_we; + logic [ 7:0] operand0_r; + logic [ 7:0] operand0_next; + + logic operand1_we; + logic [ 7:0] operand1_r; + logic [ 7:0] operand1_next; + + logic [ 7:0] decoder_instr0_selected; + logic [ 7:0] decoder_instr1_selected; + logic [ 7:0] decoder_instr2_selected; + logic decoder_need_instr1; + logic decoder_need_instr2; + logic decoder_is_undef; + + logic is_undef; + logic pc_incr; + logic instr_valid; + + `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 - always_ff @(posedge clk_i or negedge nreset_i) begin - if (~nreset_i) - pc_r <= '0; - else if (pc_we) - pc_r <= pc_next; - end + `DEF_FF(state_r, state_next, state_we, ST0_ADDR); + `DEF_FF(pc_r, pc_next, pc_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); + `DEF_FF(operand1_r, operand1_next, operand1_we, '0); - assign pc_we = (state_r == ST0_ADDR); + assign pc_we = nreset_r & pc_incr & ~is_undef; assign pc_next = (pc_r + 16'b1); + assign instr_we = (state_r == ST1_DEC); + assign instr_next = rdata_i; + + assign instr_pc_we = (state_r == ST0_ADDR); + assign instr_pc_next = pc_r; + + assign operand0_we = (state_r == ST2_DEC); + assign operand0_next = rdata_i; + + assign operand1_we = (state_r == ST3_DEC); + assign operand1_next = rdata_i; + + assign state_we = nreset_r & ~is_undef; always_comb begin case (state_r) ST0_ADDR: state_next = ST1_DEC; - ST1_DEC: state_next = ST2_EXEC; - ST2_EXEC: state_next = ST3_INC_ADDR; - ST3_INC_ADDR: state_next = ST0_ADDR; + ST1_DEC: state_next = decoder_need_instr1 ? ST2_DEC : ST2_EXEC; + ST2_EXEC: state_next = ST0_ADDR; + + ST2_DEC: state_next = decoder_need_instr2 ? ST3_DEC : ST0_ADDR; + ST3_DEC: state_next = ST4_EXEC; + ST4_EXEC: state_next = ST0_ADDR; endcase end + decode decode_inst ( + .instr0_i (decoder_instr0_selected), + .instr1_i (decoder_instr1_selected), + .instr2_i (decoder_instr2_selected), + .need_instr1_o(decoder_need_instr1), + .need_instr2_o(decoder_need_instr2), + .undef_o (decoder_is_undef) + ); + + assign decoder_instr0_selected = (state_r == ST1_DEC) ? rdata_i : instr_r; + assign decoder_instr1_selected = (state_r == ST2_DEC) ? rdata_i : operand0_r; + 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 pc_incr = (state_r == ST0_ADDR) | (state_r == ST1_DEC & decoder_need_instr1) | (state_r == ST2_DEC & decoder_need_instr2); + assign state_o = state_r; assign pc_o = pc_r; + assign instr_valid_o = instr_valid; + assign instr_undef_o = is_undef; + + assign operand8_o = operand0_r; + assign operand16_o = {operand1_r, operand0_r}; + endmodule : control diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv index 6ad95bf..60e8fad 100644 --- a/rtl/cpu/cpu.sv +++ b/rtl/cpu/cpu.sv @@ -17,6 +17,7 @@ module cpu ( control control_inst ( .clk_i (clk_i), .nreset_i(nreset_i), + .rdata_i (rdata_i), .state_o (state), .pc_o (pc) ); diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh index 1d3938e..3e2eef7 100644 --- a/rtl/cpu/cpu_pkg.svh +++ b/rtl/cpu/cpu_pkg.svh @@ -4,7 +4,10 @@ package cpu_pkg; ST0_ADDR, ST1_DEC, ST2_EXEC, - ST3_INC_ADDR + ST2_DEC, + ST3_INC_ADDR, + ST3_DEC, + ST4_EXEC } state_t; endpackage diff --git a/rtl/cpu/decode.sv b/rtl/cpu/decode.sv new file mode 100644 index 0000000..c0b5d41 --- /dev/null +++ b/rtl/cpu/decode.sv @@ -0,0 +1,21 @@ +module decode ( + input [7:0] instr0_i, + input [7:0] instr1_i, + input [7:0] instr2_i, + + output logic need_instr1_o, + output logic need_instr2_o, + output logic undef_o +); + + logic is_ld_sp_nnnn; + + + assign is_ld_sp_nnnn = (instr0_i == 7'h31); + + assign need_instr1_o = is_ld_sp_nnnn; + assign need_instr2_o = is_ld_sp_nnnn; + + assign undef_o = ~is_ld_sp_nnnn; + +endmodule : decode \ No newline at end of file diff --git a/sim/shared/clkgen.sv b/sim/shared/clkgen.sv index d070f30..851d10d 100644 --- a/sim/shared/clkgen.sv +++ b/sim/shared/clkgen.sv @@ -7,7 +7,7 @@ module clkgen #( ); initial begin - clk_o <= 1'b0; + clk_o <= 1'b1; nreset_o <= 1'b0; #RESET_DELAY_NS nreset_o <= 1'b1; end