svgb/rtl/display.sv

116 lines
2.9 KiB
Systemverilog

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