diff --git a/rtl/ppu.sv b/rtl/ppu.sv index 632825a..9eba262 100644 --- a/rtl/ppu.sv +++ b/rtl/ppu.sv @@ -8,20 +8,77 @@ module ppu ( input logic [ 7:0] cpu_wdata_i ); -logic ly_sel; -logic [ 7:0] ly_r; -logic ly_we; +`define IOREG_DECL(name) \ + logic [ 7:0] name``_r; \ + logic [ 7:0] name``_next; \ + logic name``_we; \ + logic name``_sel; -assign ly_sel = (cpu_addr_i == 16'hFF44); -assign ly_we = ly_sel & cpu_we_i; +`define IOREG_DEF(name, addr, rstval) \ + always_ff @(posedge clk or negedge nreset) begin \ + if (!nreset) \ + name``_r <= rstval; \ + else if (name``_we) \ + name``_r <= name``_next; \ + end \ + assign name``_sel = (cpu_addr_i == addr); \ + assign name``_we = name``_we & cpu_we_i; + +typedef struct packed { + logic lcd_en; + logic win_tilemap_sel; + logic win_en; + logic tiledata_sel; + logic bg_tilemap_sel; + logic obj_size; + logic obj_display; + logic bgwin_display; +} lcdc_t; + +lcdc_t lcdc; +logic [3:0] [1:0] bgp; + +`IOREG_DECL(lcdc); +`IOREG_DECL(ly); +`IOREG_DECL(sy); +`IOREG_DECL(bgp); + +`IOREG_DEF (lcdc, 16'hFF40, '0); +`IOREG_DEF ( sy, 16'hFF42, '0); +`IOREG_DEF ( bgp, 16'hFF47, '0); + +assign lcdc_next = cpu_wdata_i; +assign sy_next = cpu_wdata_i; +assign bgp_next = cpu_wdata_i; + +assign lcdc = lcdc_r; +assign bgp = bgp_r; always_ff @(posedge clk or negedge nreset) begin if (!nreset) - ly_r <= 8'h90; // vsync hack - else if (ly_we) - ly_r <= 8'h90; + ly_r <= '0; + else + ly_r <= ly_next; end -assign cpu_rdata_o = {8{ly_sel}} & ly_r; +assign ly_sel = (cpu_addr_i == 16'hFF44); +assign ly_we = ly_sel & cpu_we_i; +assign ly_next = ly_we ? 8'h00 : 8'h90; // vsync hack + +assign cpu_rdata_o = + {8{lcdc_sel}} & lcdc_r | + {8{ ly_sel}} & ly_r | + {8{ sy_sel}} & sy_r; + +`undef IOREG_DEF +`undef IOREG_DECL + +`ifdef SVA_ENABLE + +logic sva_ppu_sel; + +assign sva_ppu_sel = lcdc_sel | ly_sel | sy_sel; + +`endif /* SVA_ENABLE */ endmodule : ppu diff --git a/sim/tb_top.sv b/sim/tb_top.sv index 2c5c069..d966703 100644 --- a/sim/tb_top.sv +++ b/sim/tb_top.sv @@ -39,6 +39,12 @@ cart cart_inst ( .data_io (gb_cart_data) ); + +`ifdef SVA_ENABLE +`include "sva_common.svh" +`SVA_DEF_CLK(clk); +`SVA_DEF_NRESET(nreset); + logic instr_valid; logic instr_undef; logic halted; @@ -51,6 +57,7 @@ logic [ 7:0] last_write_value; logic vram_sel; logic hiram_sel; +logic ppu_sel; assign halted = gb_inst.cpu_inst.ctrl_inst.halted_r; assign instr_valid = gb_inst.cpu_inst.instr_valid; @@ -61,6 +68,7 @@ assign we = gb_inst.cpu_we; assign vram_sel = gb_inst.vram_sel; assign hiram_sel = gb_inst.hiram_sel; +assign ppu_sel = gb_inst.ppu_inst.sva_ppu_sel; always_ff @(posedge clk or negedge nreset) begin if (!nreset) @@ -79,19 +87,14 @@ always_ff @(posedge clk or negedge nreset) begin end end - -// SVA code here -`include "sva_common.svh" -`SVA_DEF_CLK(clk); -`SVA_DEF_NRESET(nreset); - `SVA_ASSERT_PROP_FATAL(undefined_opcode_pushed, halted |-> !instr_undef, $sformatf("PC: 0x%X | Undefined opcode pushed: 0x%X (0x%X, 0x%X)", current_pc, current_opcode[0], current_opcode[1], current_opcode[2]) ); logic selected_memory_implemented; -assign selected_memory_implemented = hiram_sel | vram_sel; + +assign selected_memory_implemented = hiram_sel | vram_sel | ppu_sel; `SVA_ASSERT_PROP(write_to_unimplemented_memory, we |-> selected_memory_implemented, @@ -99,4 +102,5 @@ assign selected_memory_implemented = hiram_sel | vram_sel; current_pc, last_write_address, last_write_value) ); +`endif /* SVA_ENABLE */ endmodule : tb_top