Starting work on PPU -> display -> VGA
This commit is contained in:
115
rtl/display.sv
Normal file
115
rtl/display.sv
Normal 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
|
||||
19
rtl/gb.sv
19
rtl/gb.sv
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user