ec82764bef
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression (272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps, and all dump-derived textures/traces) is excluded via .gitignore and stays local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
3.0 KiB
Systemverilog
75 lines
3.0 KiB
Systemverilog
// retroDE_ps2 — gs_texel_addr
|
|
//
|
|
// Texture-sampling address generator (brick 1, step 1 of GS texturing).
|
|
//
|
|
// Given a texture coordinate (u,v) and the TEX0 texture descriptor, computes
|
|
// the LINEAR VRAM byte address of that texel — the read-side mirror of the
|
|
// rasterizer's existing framebuffer-address math (gs_stub.sv ~line 530:
|
|
// fb_addr = base + (Y*FBW*64 + X) * bytes_per_pixel ).
|
|
//
|
|
// Linear (non-swizzled) only, on purpose: the swizzle paths in gs_stub are
|
|
// param-gated OFF by default, so linear is the baseline. Swizzled texel
|
|
// addressing will reuse the existing gs_swizzle_* modules later.
|
|
//
|
|
// `base_byte_addr` is the texture base in VRAM, ALREADY scaled to bytes by
|
|
// the caller from TEX0.TBP0. Keeping the base as a byte input (rather than
|
|
// scaling TBP0 here) isolates the one thing that must be reconciled with the
|
|
// texture-UPLOAD path (gif_image_xfer_stub / BITBLTBUF) — so we read texels
|
|
// from exactly where BITBLT wrote them. That reconciliation is tracked as the
|
|
// next integration step; this module's (u,v)->offset math is unambiguous and
|
|
// unit-tested below.
|
|
|
|
`timescale 1ns/1ps
|
|
|
|
module gs_texel_addr #(
|
|
parameter int ADDR_W = 32
|
|
) (
|
|
input logic [31:0] base_byte_addr, // texture base in VRAM (bytes)
|
|
input logic [10:0] u, // texel column (0..2047)
|
|
input logic [10:0] v, // texel row (0..2047)
|
|
input logic [13:0] tbw, // TEX0.TBW — texels-per-row / 64
|
|
input logic [5:0] psm, // pixel storage mode
|
|
output logic [ADDR_W-1:0] texel_byte_addr,
|
|
output logic nibble_hi // PSMT4: high nibble of the byte?
|
|
);
|
|
|
|
localparam logic [5:0] PSMCT32 = 6'h00;
|
|
localparam logic [5:0] PSMCT16 = 6'h02;
|
|
localparam logic [5:0] PSMT8 = 6'h13;
|
|
localparam logic [5:0] PSMT4 = 6'h14;
|
|
|
|
// texels per row = TBW * 64
|
|
logic [19:0] row_texels;
|
|
// linear texel index = v * row_texels + u
|
|
logic [31:0] texel_offset;
|
|
|
|
always_comb begin
|
|
row_texels = {tbw, 6'b000000}; // tbw * 64
|
|
texel_offset = (v * row_texels) + {21'd0, u};
|
|
|
|
unique case (psm)
|
|
PSMCT32: begin
|
|
texel_byte_addr = base_byte_addr + (texel_offset << 2); // 4 B/texel
|
|
nibble_hi = 1'b0;
|
|
end
|
|
PSMCT16: begin
|
|
texel_byte_addr = base_byte_addr + (texel_offset << 1); // 2 B/texel
|
|
nibble_hi = 1'b0;
|
|
end
|
|
PSMT8: begin
|
|
texel_byte_addr = base_byte_addr + texel_offset; // 1 B/texel
|
|
nibble_hi = 1'b0;
|
|
end
|
|
PSMT4: begin
|
|
texel_byte_addr = base_byte_addr + (texel_offset >> 1); // 4 b/texel
|
|
nibble_hi = texel_offset[0];
|
|
end
|
|
default: begin
|
|
texel_byte_addr = base_byte_addr + (texel_offset << 2);
|
|
nibble_hi = 1'b0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
endmodule : gs_texel_addr
|