// retroDE_ps2 — gs_tile_ram (Ch303)
//
// Generic on-chip TILE-LOCAL RAM for the tiled GS renderer: a single-write /
// single-read scratchpad sized to one render tile (e.g. 16x16 = 256 entries).
// Instantiated TWICE by the tile renderer — once as the color tile, once as the
// Z tile — so a combined textured+alpha+depth pixel resolves its color/Z
// read-modify-write entirely ON CHIP (per docs/decisions/0008 §6), with only the
// texture fetch and the per-tile flush crossing to VRAM/LPDDR.
//
// Contract (matches vram_bram_stub.read2 so the raster FSM retarget is minimal):
//   - 1 write port (we/waddr/wdata), committed this cycle.
//   - 1 read port (raddr), data REGISTERED → valid ONE cycle later (rdata).
//   - Same-address read+write in the same cycle is NOT used by the tile renderer
//     (the FSM reads Z at beat 0 and writes Z at beat 4 of a 5-beat pixel; color
//     read at beat 2, write at beat 3 — never the same cycle), so no R/W-collision
//     forwarding is needed; this stays a plain 1W1R inferred BRAM.
//
// The memory is NOT reset (BRAM-friendly); the renderer's CLEAR phase initializes
// every entry (color=clear color, Z=clear/far Z) before the first primitive.

`timescale 1ns/1ps

module gs_tile_ram #(
    parameter int ADDR_W = 8,    // 256 entries = one 16x16 tile
    parameter int DATA_W = 32
) (
    input  logic              clk,
    input  logic              rst_n,
    // write port (1 cycle, committed)
    input  logic              we,
    input  logic [ADDR_W-1:0] waddr,
    input  logic [DATA_W-1:0] wdata,
    // read port (registered, valid 1 cycle after raddr presented)
    input  logic [ADDR_W-1:0] raddr,
    output logic [DATA_W-1:0] rdata
);
    logic [DATA_W-1:0] mem [0:(1<<ADDR_W)-1];

    always_ff @(posedge clk) begin
        if (!rst_n) begin
            rdata <= '0;
        end else begin
            if (we) mem[waddr] <= wdata;
            rdata <= mem[raddr];        // 1-cycle registered read
        end
    end

endmodule : gs_tile_ram
