diff --git a/build/tb_top.Makefile b/build/tb_top.Makefile index 8114232..480d731 100644 --- a/build/tb_top.Makefile +++ b/build/tb_top.Makefile @@ -1,5 +1,8 @@ TB = tb_top -SOURCES = gb.sv tb_top.sv -PATH_SRC = ../rtl:../sim/tbench +SOURCES = gb.sv cpu.sv registers.sv control.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 include ../synthflow/vivado/Makefile.rules \ No newline at end of file diff --git a/rtl/cpu/control.sv b/rtl/cpu/control.sv new file mode 100644 index 0000000..b043132 --- /dev/null +++ b/rtl/cpu/control.sv @@ -0,0 +1,49 @@ +`include "cpu_pkg.svh" + +import cpu_pkg::*; + +module control ( + input logic clk_i, + input logic nreset_i, + output state_t state_o, + + output logic [15:0] pc_o +); + + state_t state_r; + state_t state_next; + + logic pc_we; + 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; + 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 + + assign pc_we = (state_r == ST0_ADDR); + assign pc_next = (pc_r + 16'b1); + + 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; + endcase + end + + assign state_o = state_r; + assign pc_o = pc_r; + +endmodule : control diff --git a/rtl/cpu/cpu.sv b/rtl/cpu/cpu.sv new file mode 100644 index 0000000..6ad95bf --- /dev/null +++ b/rtl/cpu/cpu.sv @@ -0,0 +1,31 @@ +`include "cpu_pkg.svh" + +import cpu_pkg::*; + +module cpu ( + input logic clk_i, + input logic nreset_i, + + output logic [15:0] address_o, + input logic [ 7:0] rdata_i +); + + state_t state; + + logic [15:0] pc; + + control control_inst ( + .clk_i (clk_i), + .nreset_i(nreset_i), + .state_o (state), + .pc_o (pc) + ); + + registers registers_inst ( + .clk_i (clk_i), + .nreset_i(nreset_i) + ); + + assign address_o = pc; + +endmodule : cpu diff --git a/rtl/cpu/cpu_pkg.svh b/rtl/cpu/cpu_pkg.svh new file mode 100644 index 0000000..1d3938e --- /dev/null +++ b/rtl/cpu/cpu_pkg.svh @@ -0,0 +1,10 @@ +package cpu_pkg; + + typedef enum { + ST0_ADDR, + ST1_DEC, + ST2_EXEC, + ST3_INC_ADDR + } state_t; + +endpackage diff --git a/rtl/cpu/registers.sv b/rtl/cpu/registers.sv new file mode 100644 index 0000000..cd72197 --- /dev/null +++ b/rtl/cpu/registers.sv @@ -0,0 +1,6 @@ +module registers ( + input logic clk_i, + input logic nreset_i +); + +endmodule : registers diff --git a/rtl/gb.sv b/rtl/gb.sv index 1f695ae..3b3e715 100644 --- a/rtl/gb.sv +++ b/rtl/gb.sv @@ -3,6 +3,24 @@ module gb ( input logic nreset_i ); + logic [15:0] address; + logic [ 7:0] rdata; + cpu cpu_inst ( + .clk_i (clk_i), + .nreset_i (nreset_i), + .address_o(address), + .rdata_i (rdata) + ); + + rom #( + .FILE_NAME("DMG_ROM.bin"), + .ADDR_W (8), + .DATA_W (8) + ) rom_inst ( + .clk_i (clk_i), + .address_i(address[7:0]), + .rdata_o (rdata) + ); endmodule : gb diff --git a/rtl/shared/rom.sv b/rtl/shared/rom.sv new file mode 100644 index 0000000..e716117 --- /dev/null +++ b/rtl/shared/rom.sv @@ -0,0 +1,24 @@ +module rom #( + parameter string FILE_NAME = "", + parameter integer unsigned ADDR_W = 8, + parameter integer unsigned DATA_W = 8 +) ( + input logic clk_i, + input logic [ADDR_W-1:0] address_i, + + output logic [DATA_W-1:0] rdata_o +); + +localparam ROM_SIZE = 2**ADDR_W; + +logic [DATA_W-1:0] rom [ROM_SIZE-1:0]; + +always_ff @(posedge clk_i) + rdata_o <= rom[address_i]; + +initial begin + static integer fd = $fopen(FILE_NAME, "rb"); + void'($fread(rom, fd)); +end + +endmodule : rom diff --git a/sim/shared/clkgen.sv b/sim/shared/clkgen.sv new file mode 100644 index 0000000..d070f30 --- /dev/null +++ b/sim/shared/clkgen.sv @@ -0,0 +1,18 @@ +module clkgen #( + PERIOD_NS = 10, + RESET_DELAY_NS = 100 +) ( + output logic clk_o, + output logic nreset_o +); + + initial begin + clk_o <= 1'b0; + nreset_o <= 1'b0; + #RESET_DELAY_NS nreset_o <= 1'b1; + end + + always + #(PERIOD_NS/2) clk_o <= ~clk_o; + +endmodule diff --git a/sim/tbench/tb_top.sv b/sim/tbench/tb_top.sv index 3827e5c..3451729 100644 --- a/sim/tbench/tb_top.sv +++ b/sim/tbench/tb_top.sv @@ -3,19 +3,15 @@ module tb_top (); logic clk; logic nreset; + clkgen clkgen_inst ( + .clk_o (clk), + .nreset_o(nreset) + ); + gb gb_inst ( .clk_i (clk), .nreset_i(nreset) ); - initial begin - clk = 1'b0; - nreset = 1'b1; - - #1 nreset = 1'b0; - #24 nreset = 1'b1; - end // initial - - always #5 clk = ~clk; endmodule : tb_top