116 lines
2.9 KiB
Systemverilog
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
|