WIP PPU LX/LY registers
Removed second reg16 read port - no longer needed.
This commit is contained in:
101
rtl/ppu/ppu.sv
Normal file
101
rtl/ppu/ppu.sv
Normal file
@@ -0,0 +1,101 @@
|
||||
module ppu (
|
||||
input logic clk,
|
||||
input logic nreset,
|
||||
|
||||
input logic [15:0] cpu_addr_i,
|
||||
output logic [ 7:0] cpu_rdata_o,
|
||||
input logic cpu_we_i,
|
||||
input logic [ 7:0] cpu_wdata_i
|
||||
);
|
||||
|
||||
`define IOREG_DECL(name) \
|
||||
logic [ 7:0] name``_r; \
|
||||
logic [ 7:0] name``_next; \
|
||||
logic name``_we; \
|
||||
logic name``_sel;
|
||||
|
||||
`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;
|
||||
|
||||
// LX is not read/writeable
|
||||
logic [ 8:0] lx_r;
|
||||
logic [ 8:0] lx_next;
|
||||
logic lx_end_of_line;
|
||||
logic ly_end_of_frame;
|
||||
|
||||
`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) begin
|
||||
ly_r <= '0;
|
||||
lx_r <= '0;
|
||||
end else begin
|
||||
ly_r <= ly_next;
|
||||
lx_r <= lx_next;
|
||||
end
|
||||
end
|
||||
|
||||
assign ly_sel = (cpu_addr_i == 16'hFF44);
|
||||
assign ly_next = (ly_sel & cpu_we_i) ? 8'h00 : // Clear on write
|
||||
(lx_end_of_line & ly_end_of_frame) ? 8'h00 :
|
||||
(lx_end_of_line & ~ly_end_of_frame) ? (ly_r + 8'h01) :
|
||||
ly_r;
|
||||
|
||||
assign lx_next = lx_end_of_line ? 8'h0 : (lx_r + 8'h01);
|
||||
|
||||
assign ly_end_of_frame = ly_r > 8'd153;
|
||||
assign lx_end_of_line = lx_r > 9'd456;
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user