Starting work on PPU -> display -> VGA

This commit is contained in:
2023-10-13 20:46:05 +01:00
parent bfcdec1d83
commit 3c3dbd2175
10 changed files with 600 additions and 20 deletions

115
rtl/display.sv Normal file
View File

@@ -0,0 +1,115 @@
module display #(
parameter VGA_DEPTH = 8,
parameter VGA_W = 640,
parameter VGA_H = 480
) (
input logic nreset,
input logic display_enable_i,
input logic ppu_clk,
input logic [ 1:0] ppu_pixel_i,
input logic ppu_vsync_i,
input logic ppu_hsync_i,
// RGB ppu_pixel
input logic [ 2:0][VGA_DEPTH-1:0] VGA_PALETTE[3:0],
input logic vga_clk,
output logic [VGA_DEPTH-1:0] vga_r_o,
output logic [VGA_DEPTH-1:0] vga_g_o,
output logic [VGA_DEPTH-1:0] vga_b_o,
output logic vga_hsync_o,
output logic vga_vsync_o
);
localparam DISPLAY_W = 160;
localparam DISPLAY_H = 144;
localparam BUFFER_SIZE = DISPLAY_W * DISPLAY_H;
logic [7:0] ppu_px_r;
logic [7:0] ppu_py_r;
logic [7:0] ppu_px_next;
logic [7:0] ppu_py_next;
logic [9:0] vga_px_r;
logic [9:0] vga_py_r;
logic [9:0] vga_px_next;
logic [9:0] vga_py_next;
logic vga_vsync;
logic vga_hsync;
always_ff @(posedge ppu_clk or negedge nreset) begin
if (!nreset) begin
ppu_px_r <= '0;
ppu_py_r <= '0;
end else begin
ppu_px_r <= ppu_px_next;
ppu_py_r <= ppu_py_next;
end
end
assign ppu_px_next = ppu_hsync_i ? '0 : (ppu_px_r + 8'h01);
assign ppu_py_next = ppu_vsync_i ? '0 :
ppu_hsync_i ? (ppu_py_r + 8'h01) :
(ppu_py_r);
always_ff @(posedge vga_clk or negedge nreset) begin
if (!nreset) begin
vga_px_r <= '0;
vga_py_r <= '0;
end else begin
vga_px_r <= vga_px_next;
vga_py_r <= vga_py_next;
end
end
assign vga_px_next = vga_hsync ? '0 : (vga_px_r + 8'h01);
assign vga_py_next = vga_vsync ? '0 :
vga_hsync ? (vga_py_r + 8'h01) :
(vga_py_r);
assign vga_hsync = (vga_px_r == VGA_W);
assign vga_vsync = (vga_py_r == VGA_H);
logic [1:0] buffer_r[BUFFER_SIZE-1:0];
logic [15:0] buffer_raddr;
logic [15:0] buffer_waddr;
logic buffer_we;
always_ff @(posedge ppu_clk or negedge nreset) begin
if (!nreset) begin
buffer_r[buffer_waddr] <= '0;
end else if (buffer_we) begin
buffer_r[buffer_waddr] <= ppu_pixel_i;
end
end
assign buffer_we = ~ppu_vsync_i & ~ppu_hsync_i;
assign buffer_waddr = DISPLAY_W * ppu_py_r + ppu_px_r;
logic [1:0] buffer_rval;
always_ff @(posedge vga_clk or negedge nreset) begin
if (!nreset) begin
buffer_rval <= '0;
end else begin
buffer_rval <= buffer_r[buffer_raddr];
end
end
assign buffer_raddr = DISPLAY_W * vga_py_r + vga_py_r;
logic vga_in_display;
assign vga_in_display = (vga_py_r < DISPLAY_H) & (vga_px_r < DISPLAY_W);
assign vga_r_o = (display_enable_i & vga_in_display) ? VGA_PALETTE[buffer_rval][0] : '0;
assign vga_g_o = (display_enable_i & vga_in_display) ? VGA_PALETTE[buffer_rval][1] : '0;
assign vga_b_o = (display_enable_i & vga_in_display) ? VGA_PALETTE[buffer_rval][2] : '0;
assign vga_vsync_o = vga_vsync;
assign vga_hsync_o = vga_hsync;
endmodule : display

View File

@@ -10,7 +10,13 @@ module gb (
output wire cart_nwr_o,
output wire cart_ncs_o,
output wire [15:0] cart_addr_o,
inout wire [ 7:0] cart_data_io
inout wire [ 7:0] cart_data_io,
// PPU output to display
output logic ppu_display_enable_o,
output logic [ 1:0] ppu_pixel_o,
output logic ppu_vsync_o,
output logic ppu_hsync_o
);
@@ -24,13 +30,10 @@ logic [ 7:0] cpu_ppu_rdata;
logic rom_enable_r;
logic rom_sel;
logic [ 7:0] rom_rdata;
logic hiram_sel;
logic [ 7:0] hiram_rdata;
logic vram_sel;
logic [ 7:0] vram_rdata;
logic cart_sel;
logic [ 7:0] cart_rdata;
@@ -48,10 +51,16 @@ ppu ppu_inst (
.clk (clk),
.nreset (nreset),
.display_enable_o(ppu_display_enable_o),
.cpu_addr_i (cpu_addr),
.cpu_rdata_o(cpu_ppu_rdata),
.cpu_we_i (cpu_we),
.cpu_wdata_i(cpu_wdata)
.cpu_wdata_i(cpu_wdata),
.pixel_o (ppu_pixel_o),
.vsync_o (ppu_vsync_o),
.hsync_o (ppu_hsync_o)
);
assign rom_enable_r = '1;

View File

@@ -4,10 +4,16 @@ module ppu (
input logic clk,
input logic nreset,
output logic display_enable_o,
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
input logic [ 7:0] cpu_wdata_i,
output logic [ 1:0] pixel_o,
output logic vsync_o,
output logic hsync_o
);
`define IOREG_DECL(name) \
@@ -24,7 +30,7 @@ module ppu (
name``_r <= name``_next; \
end \
assign name``_sel = (cpu_addr_i == addr); \
assign name``_we = name``_we & cpu_we_i;
assign name``_we = name``_sel & cpu_we_i;
typedef struct packed {
logic lcd_en;
@@ -93,6 +99,14 @@ assign cpu_rdata_o =
`endif
{8{ sy_sel}} & sy_r;
assign pixel_o = ((lx_r < 8'd160) & (ly_r < 8'd144)) ? ly_r[1:0] : // should create a nice line-pattern for now
2'h00;
assign vsync_o = ly_r >= 8'd144;
assign hsync_o = lx_r >= 8'd160;
assign display_enable_o = lcdc_r[7];
`undef IOREG_DEF
`undef IOREG_DECL