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