module ppu_ioregs ( 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, output logic display_enable_o, output logic tilemap_base_sel_o, output logic [ 8:0] ly_o, output logic [ 7:0] lx_o ); `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``_sel & 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; assign cpu_rdata_o = {8{lcdc_sel}} & lcdc_r | {8{ sy_sel}} & sy_r; assign display_enable_o = lcdc.lcd_en; assign tilemap_base_sel_o = lcdc.bg_tilemap_sel; `ifdef SVA_ENABLE logic sva_sel; assign sva_sel = lcdc_sel | sy_sel; `endif /* SVA_ENABLE */ endmodule : ppu_ioregs