From 081a8a3ba8bfe036f31da53f9c041a2caa30fce2 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Sun, 5 May 2024 17:34:22 -0600 Subject: rtl/legacy_gfx: rename gfx -> legacy_gfx --- rtl/legacy_gfx/gfx_scanout.sv | 138 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 rtl/legacy_gfx/gfx_scanout.sv (limited to 'rtl/legacy_gfx/gfx_scanout.sv') diff --git a/rtl/legacy_gfx/gfx_scanout.sv b/rtl/legacy_gfx/gfx_scanout.sv new file mode 100644 index 0000000..a43d14c --- /dev/null +++ b/rtl/legacy_gfx/gfx_scanout.sv @@ -0,0 +1,138 @@ +`include "gfx/gfx_defs.sv" + +module gfx_scanout +( + input logic clk, + rst_n, + + input logic enable_clear, + input rgb24 clear_color, + input vram_addr scan_base, + + input logic mask, + output linear_coord mask_addr, + + input logic fb_waitrequest, + fb_readdatavalid, + input vram_word fb_readdata, + output logic fb_read, + output vram_addr fb_address, + + input logic scan_ready, + output logic scan_valid, + scan_endofpacket, + scan_startofpacket, + output rgb30 scan_data, + + output logic vsync +); + + logic commit, effective_mask, flush, mask_fifo_out, dac_ready, + fb_ready, mask_fifo_ready, fb_fifo_valid, mask_fifo_valid, + pop, put, put_mask, next_vsync, start_vsync, wait_vsync; + + vram_word fb_fifo_out; + half_coord commit_addr, mask_in_addr, mask_out_addr, mask_hold_addr, max_addr; + + assign mask_addr = mask_in_addr[$bits(mask_in_addr) - 1:$bits(mask_in_addr) - $bits(mask_addr)]; + assign max_addr[0] = 1; + assign max_addr[$bits(max_addr) - 1:1] = `GFX_X_RES * `GFX_Y_RES - 1; + + assign fb_ready = !fb_read || !fb_waitrequest; + assign next_vsync = commit && start_vsync; + assign start_vsync = mask_hold_addr == max_addr; + assign effective_mask = mask || !enable_clear; + + gfx_flush_flow #(.STAGES(`GFX_MASK_STAGES)) mask_flow + ( + .in_valid(!wait_vsync), + .out_ready(fb_ready && mask_fifo_ready && !next_vsync), + .out_valid(pop), + .* + ); + + gfx_pipes #(.WIDTH($bits(mask_in_addr)), .DEPTH(`GFX_MASK_STAGES)) addr_pipes + ( + .in(mask_in_addr), + .out(mask_out_addr), + .stall(0), + .* + ); + + /* Estas FIFOs deben cumplir dos propiedades para garantizar correctitud: + * + * 1. mask_fifo.out_ready && mask_fifo.out_valid <=> scan.in_ready && scan.in_valid + * 2. fb_fifo.out_ready && fb_fifo.out_valid => scan.in_ready && scan.in_valid + * + * Nótese la asimetría (<=> vs =>), debido a mask_fifo.out + */ + + gfx_fifo #(.WIDTH($bits(effective_mask)), .DEPTH(`GFX_SCANOUT_FIFO_DEPTH)) mask_fifo + ( + .in(put_mask), + .out(mask_fifo_out), + .in_ready(mask_fifo_ready), + .in_valid(put), + .out_ready(dac_ready && (!mask_fifo_out || fb_fifo_valid)), + .out_valid(mask_fifo_valid), + .* + ); + + // 2x para evitar potencial overflow cuando fb_read=1 pero mask_fifo está llena + gfx_fifo #(.WIDTH($bits(vram_word)), .DEPTH(2 * `GFX_SCANOUT_FIFO_DEPTH)) fb_fifo + ( + .in(fb_readdata), + .out(fb_fifo_out), + .in_ready(), // readdatavalid no soporta backpressure + .in_valid(fb_readdatavalid), + .out_ready(dac_ready && mask_fifo_valid && mask_fifo_out), + .out_valid(fb_fifo_valid), + .* + ); + + gfx_scanout_dac dac + ( + .in_ready(dac_ready), + .in_valid(mask_fifo_valid && (!mask_fifo_out || fb_fifo_valid)), + .* + ); + + always_ff @(posedge clk or negedge rst_n) + if (!rst_n) begin + put <= 0; + fb_read <= 0; + wait_vsync <= 0; + commit_addr <= 0; + mask_in_addr <= 0; + end else begin + mask_in_addr <= mask_in_addr + 1; + + if (flush || wait_vsync) + mask_in_addr <= commit_addr; + + if (commit) begin + wait_vsync <= start_vsync; + commit_addr <= start_vsync ? 0 : mask_out_addr; + end + + if (fb_ready) + fb_read <= mask_fifo_ready && pop && !next_vsync && effective_mask; + + if (mask_fifo_ready) + put <= fb_ready && pop && !next_vsync; + + if (vsync) + wait_vsync <= 0; + end + + always_ff @(posedge clk) begin + mask_hold_addr <= mask_out_addr; + + if (fb_ready) + fb_address <= scan_base + {5'd0, mask_out_addr}; + + if (mask_fifo_ready) + put_mask <= effective_mask; + end + +endmodule -- cgit v1.2.3