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>
340 lines
24 KiB
Systemverilog
340 lines
24 KiB
Systemverilog
// retroDE_ps2 — gs_swizzle_psmt4_stub (Ch137)
|
||
//
|
||
// Pure-combinational PSMT4 page/block/column swizzle: maps a
|
||
// pixel coordinate (x, y) within a framebuffer at (FBP, FBW) to
|
||
// its physical VRAM byte address AND high/low nibble select
|
||
// using the real PS2 GS PSMT4 layout. Mirrors Ch119's PSMCT32 +
|
||
// Ch125's PSMCT16 + Ch131's PSMT8 stubs but with PSMT4's wider
|
||
// 32-px-wide block, 32×16 within-block nibble layout, and the
|
||
// half-byte addressing distinction (each PSMT4 pixel is 4 bits;
|
||
// two PSMT4 pixels share a byte). Output `nibble_hi` selects
|
||
// which nibble of the byte at `addr` the pixel occupies.
|
||
//
|
||
// THIS MODULE IS NOT YET WIRED INTO gs_pcrtc_stub /
|
||
// gif_image_xfer_stub / gs_stub. Future chapters will wire it
|
||
// behind a `PSMT4_SWIZZLE`-style parameter gate, mirroring the
|
||
// PSMCT32 (Ch120/121/122), PSMCT16 (Ch126/127/128), and PSMT8
|
||
// (Ch132/133/134) progressions. Default-off keeps the legacy
|
||
// linear PSMT4 TBs (Ch103, Ch106, Ch118, Ch107 e2e palette path)
|
||
// on the linear path. The existing per-bit write_mask 0x0F/0xF0
|
||
// nibble RMW from Ch106/Ch118 will still apply on top of the
|
||
// swizzled byte address — the swizzle doesn't touch the nibble
|
||
// merge logic.
|
||
//
|
||
// SOURCE-TABLE PROVENANCE (per Codex's Ch125/Ch131/Ch137 guidance):
|
||
// blockTable4 — pcsx2/GS/GSTables.cpp lines 61–69, master
|
||
// HEAD commit 3000e113e2b3a76357c08dfa80d3c747f40e2706
|
||
// (file blob SHA 3581209b8217378f473f9de22a9dbc8c45ca49b6).
|
||
// 8 rows × 4 cols, indexed [block_y][block_x].
|
||
// columnTable4 — pcsx2/GS/GSTables.cpp lines 147–213, same
|
||
// commit. 16 rows × 32 cols, indexed [yb][xb],
|
||
// values are nibble-within-block (0..511).
|
||
// Cross-check — GSLocalMemory.h:558 BlockNumber4 + the
|
||
// pxOffset template at GSTables.cpp:247–258
|
||
// (blockSize=512, pageSize=16384, pageWidth=128,
|
||
// note `blockSize` here is in NIBBLES; byte-
|
||
// grain pageSize = 8192 = 16384 nibbles / 2).
|
||
// PSMT4 has pageShiftX=7, pageShiftY=7,
|
||
// blockShiftX=5, blockShiftY=4,
|
||
// m_bwPg = bw >> (pageShiftX - 6) = bw >> 1
|
||
// (so FBW must be even for PSMT4 — PCSX2 asserts
|
||
// `(bw & 1) == 0` at GSLocalMemory.h:560).
|
||
// PCSX2's `bp` is in 256-byte block-pointer
|
||
// units; in our FBP (2048-byte) units,
|
||
// bp = FBP * 8, so bp*256 = FBP*2048.
|
||
//
|
||
// NOTE on PCSX2 license: the PCSX2 project is GPL-3.0+. This
|
||
// stub re-expresses the same PSMT4 swizzle math in SystemVerilog
|
||
// as a hardware contract — the values in the blockTable4 /
|
||
// columnTable4 case statements come from PCSX2 source and
|
||
// represent the PS2 hardware layout itself (not PCSX2-original
|
||
// creative content). The retroDE_ps2 project authors should
|
||
// consider whether this provenance affects licensing for
|
||
// downstream consumers; from an engineering correctness
|
||
// standpoint, locking against the canonical source is the only
|
||
// way to be byte-accurate to real PS2 VRAM.
|
||
//
|
||
// Real PS2 PSMT4 layout:
|
||
// - VRAM is 4 MiB total, organized in 8 KiB pages.
|
||
// - Each page is 128×128 PSMT4 pixels (= 128*128/2 = 8192
|
||
// bytes — 2 PSMT4 pixels per byte). 4× as many pixels per
|
||
// page as PSMT8 (128×64) and same byte stride.
|
||
// - Each page is divided into a 4×8 grid of blocks (4 cols of
|
||
// blocks across, 8 rows down). Each block is 32×16 PSMT4
|
||
// pixels (= 32*16/2 = 256 bytes = 512 nibbles). 4×8 = 32
|
||
// blocks/page (same number of blocks as the other PSMs).
|
||
// - Block ordering within a page follows blockTable4 (which
|
||
// happens to be identical to PSMCT16's blockTable16 — both
|
||
// PSMs share the same block grid orientation).
|
||
// - Within a block, NIBBLE placement follows columnTable4: a
|
||
// 32×16 → 512-entry permutation that organizes the internal
|
||
// 8-wide × 4-tall sub-columns and 4-tall row-groups of the
|
||
// block.
|
||
//
|
||
// Address formula (FBP in 2048-byte units; FBW in 64-pixel
|
||
// units; addr in BYTES; FBW must be even):
|
||
// page_x = x / 128
|
||
// page_y = y / 128
|
||
// bw_pg = FBW / 2 // pages per row
|
||
// page_index = page_y * bw_pg + page_x
|
||
// page_base = FBP*2048 + page_index*8192
|
||
//
|
||
// block_x_in_page = (x % 128) / 32 // 0..3
|
||
// block_y_in_page = (y % 128) / 16 // 0..7
|
||
// block_idx = blockTable4[block_y_in_page][block_x_in_page]
|
||
// block_base = page_base + block_idx*256
|
||
//
|
||
// xb = x % 32
|
||
// yb = y % 16
|
||
// nibble_idx = columnTable4[yb][xb] // 0..511
|
||
// byte_in_block = nibble_idx >> 1 // 0..255
|
||
// addr = block_base + byte_in_block
|
||
// nibble_hi = nibble_idx[0] // 0=low nibble, 1=high
|
||
|
||
`timescale 1ns/1ps
|
||
|
||
module gs_swizzle_psmt4_stub
|
||
(
|
||
input logic [8:0] fbp, // FBP — frame base, in 2048-byte units
|
||
input logic [5:0] fbw, // FBW — frame width, in 64-pixel units (must be even)
|
||
input logic [11:0] x,
|
||
input logic [11:0] y,
|
||
output logic [31:0] addr,
|
||
output logic nibble_hi
|
||
);
|
||
|
||
// --------------------------------------------------------------
|
||
// blockTable4 (verbatim from pcsx2/GS/GSTables.cpp lines 61–69).
|
||
// Indexed [block_y_in_page (0..7)][block_x_in_page (0..3)].
|
||
// by=0: { 0, 2, 8, 10 }
|
||
// by=1: { 1, 3, 9, 11 }
|
||
// by=2: { 4, 6, 12, 14 }
|
||
// by=3: { 5, 7, 13, 15 }
|
||
// by=4: { 16, 18, 24, 26 }
|
||
// by=5: { 17, 19, 25, 27 }
|
||
// by=6: { 20, 22, 28, 30 }
|
||
// by=7: { 21, 23, 29, 31 }
|
||
// --------------------------------------------------------------
|
||
function automatic logic [4:0] swizzle_psmt4(
|
||
input logic [2:0] by,
|
||
input logic [1:0] bx);
|
||
case ({by, bx})
|
||
5'd0: return 5'd0; 5'd1: return 5'd2; 5'd2: return 5'd8; 5'd3: return 5'd10;
|
||
5'd4: return 5'd1; 5'd5: return 5'd3; 5'd6: return 5'd9; 5'd7: return 5'd11;
|
||
5'd8: return 5'd4; 5'd9: return 5'd6; 5'd10: return 5'd12; 5'd11: return 5'd14;
|
||
5'd12: return 5'd5; 5'd13: return 5'd7; 5'd14: return 5'd13; 5'd15: return 5'd15;
|
||
5'd16: return 5'd16; 5'd17: return 5'd18; 5'd18: return 5'd24; 5'd19: return 5'd26;
|
||
5'd20: return 5'd17; 5'd21: return 5'd19; 5'd22: return 5'd25; 5'd23: return 5'd27;
|
||
5'd24: return 5'd20; 5'd25: return 5'd22; 5'd26: return 5'd28; 5'd27: return 5'd30;
|
||
5'd28: return 5'd21; 5'd29: return 5'd23; 5'd30: return 5'd29; default: return 5'd31;
|
||
endcase
|
||
endfunction
|
||
|
||
// --------------------------------------------------------------
|
||
// columnTable4 (verbatim from pcsx2/GS/GSTables.cpp lines 147–213).
|
||
// Indexed [yb (0..15)][xb (0..31)] → nibble-within-block 0..511.
|
||
// 512 entries total. Encoded as one large case statement on
|
||
// {yb, xb} (4+5 = 9 bits). Comments separate yb-block boundaries.
|
||
// --------------------------------------------------------------
|
||
function automatic logic [8:0] col_idx_psmt4(
|
||
input logic [3:0] yb,
|
||
input logic [4:0] xb);
|
||
case ({yb, xb})
|
||
// yb=0: 0 8 32 40 64 72 96 104 2 10 34 42 66 74 98 106
|
||
// 4 12 36 44 68 76 100 108 6 14 38 46 70 78 102 110
|
||
9'd0: return 9'd0; 9'd1: return 9'd8; 9'd2: return 9'd32; 9'd3: return 9'd40;
|
||
9'd4: return 9'd64; 9'd5: return 9'd72; 9'd6: return 9'd96; 9'd7: return 9'd104;
|
||
9'd8: return 9'd2; 9'd9: return 9'd10; 9'd10: return 9'd34; 9'd11: return 9'd42;
|
||
9'd12: return 9'd66; 9'd13: return 9'd74; 9'd14: return 9'd98; 9'd15: return 9'd106;
|
||
9'd16: return 9'd4; 9'd17: return 9'd12; 9'd18: return 9'd36; 9'd19: return 9'd44;
|
||
9'd20: return 9'd68; 9'd21: return 9'd76; 9'd22: return 9'd100; 9'd23: return 9'd108;
|
||
9'd24: return 9'd6; 9'd25: return 9'd14; 9'd26: return 9'd38; 9'd27: return 9'd46;
|
||
9'd28: return 9'd70; 9'd29: return 9'd78; 9'd30: return 9'd102; 9'd31: return 9'd110;
|
||
// yb=1: 16 24 48 56 80 88 112 120 18 26 50 58 82 90 114 122
|
||
// 20 28 52 60 84 92 116 124 22 30 54 62 86 94 118 126
|
||
9'd32: return 9'd16; 9'd33: return 9'd24; 9'd34: return 9'd48; 9'd35: return 9'd56;
|
||
9'd36: return 9'd80; 9'd37: return 9'd88; 9'd38: return 9'd112; 9'd39: return 9'd120;
|
||
9'd40: return 9'd18; 9'd41: return 9'd26; 9'd42: return 9'd50; 9'd43: return 9'd58;
|
||
9'd44: return 9'd82; 9'd45: return 9'd90; 9'd46: return 9'd114; 9'd47: return 9'd122;
|
||
9'd48: return 9'd20; 9'd49: return 9'd28; 9'd50: return 9'd52; 9'd51: return 9'd60;
|
||
9'd52: return 9'd84; 9'd53: return 9'd92; 9'd54: return 9'd116; 9'd55: return 9'd124;
|
||
9'd56: return 9'd22; 9'd57: return 9'd30; 9'd58: return 9'd54; 9'd59: return 9'd62;
|
||
9'd60: return 9'd86; 9'd61: return 9'd94; 9'd62: return 9'd118; 9'd63: return 9'd126;
|
||
// yb=2: 65 73 97 105 1 9 33 41 67 75 99 107 3 11 35 43
|
||
// 69 77 101 109 5 13 37 45 71 79 103 111 7 15 39 47
|
||
9'd64: return 9'd65; 9'd65: return 9'd73; 9'd66: return 9'd97; 9'd67: return 9'd105;
|
||
9'd68: return 9'd1; 9'd69: return 9'd9; 9'd70: return 9'd33; 9'd71: return 9'd41;
|
||
9'd72: return 9'd67; 9'd73: return 9'd75; 9'd74: return 9'd99; 9'd75: return 9'd107;
|
||
9'd76: return 9'd3; 9'd77: return 9'd11; 9'd78: return 9'd35; 9'd79: return 9'd43;
|
||
9'd80: return 9'd69; 9'd81: return 9'd77; 9'd82: return 9'd101; 9'd83: return 9'd109;
|
||
9'd84: return 9'd5; 9'd85: return 9'd13; 9'd86: return 9'd37; 9'd87: return 9'd45;
|
||
9'd88: return 9'd71; 9'd89: return 9'd79; 9'd90: return 9'd103; 9'd91: return 9'd111;
|
||
9'd92: return 9'd7; 9'd93: return 9'd15; 9'd94: return 9'd39; 9'd95: return 9'd47;
|
||
// yb=3: 81 89 113 121 17 25 49 57 83 91 115 123 19 27 51 59
|
||
// 85 93 117 125 21 29 53 61 87 95 119 127 23 31 55 63
|
||
9'd96: return 9'd81; 9'd97: return 9'd89; 9'd98: return 9'd113; 9'd99: return 9'd121;
|
||
9'd100: return 9'd17; 9'd101: return 9'd25; 9'd102: return 9'd49; 9'd103: return 9'd57;
|
||
9'd104: return 9'd83; 9'd105: return 9'd91; 9'd106: return 9'd115; 9'd107: return 9'd123;
|
||
9'd108: return 9'd19; 9'd109: return 9'd27; 9'd110: return 9'd51; 9'd111: return 9'd59;
|
||
9'd112: return 9'd85; 9'd113: return 9'd93; 9'd114: return 9'd117; 9'd115: return 9'd125;
|
||
9'd116: return 9'd21; 9'd117: return 9'd29; 9'd118: return 9'd53; 9'd119: return 9'd61;
|
||
9'd120: return 9'd87; 9'd121: return 9'd95; 9'd122: return 9'd119; 9'd123: return 9'd127;
|
||
9'd124: return 9'd23; 9'd125: return 9'd31; 9'd126: return 9'd55; 9'd127: return 9'd63;
|
||
// yb=4: 192 200 224 232 128 136 160 168 194 202 226 234 130 138 162 170
|
||
// 196 204 228 236 132 140 164 172 198 206 230 238 134 142 166 174
|
||
9'd128: return 9'd192; 9'd129: return 9'd200; 9'd130: return 9'd224; 9'd131: return 9'd232;
|
||
9'd132: return 9'd128; 9'd133: return 9'd136; 9'd134: return 9'd160; 9'd135: return 9'd168;
|
||
9'd136: return 9'd194; 9'd137: return 9'd202; 9'd138: return 9'd226; 9'd139: return 9'd234;
|
||
9'd140: return 9'd130; 9'd141: return 9'd138; 9'd142: return 9'd162; 9'd143: return 9'd170;
|
||
9'd144: return 9'd196; 9'd145: return 9'd204; 9'd146: return 9'd228; 9'd147: return 9'd236;
|
||
9'd148: return 9'd132; 9'd149: return 9'd140; 9'd150: return 9'd164; 9'd151: return 9'd172;
|
||
9'd152: return 9'd198; 9'd153: return 9'd206; 9'd154: return 9'd230; 9'd155: return 9'd238;
|
||
9'd156: return 9'd134; 9'd157: return 9'd142; 9'd158: return 9'd166; 9'd159: return 9'd174;
|
||
// yb=5: 208 216 240 248 144 152 176 184 210 218 242 250 146 154 178 186
|
||
// 212 220 244 252 148 156 180 188 214 222 246 254 150 158 182 190
|
||
9'd160: return 9'd208; 9'd161: return 9'd216; 9'd162: return 9'd240; 9'd163: return 9'd248;
|
||
9'd164: return 9'd144; 9'd165: return 9'd152; 9'd166: return 9'd176; 9'd167: return 9'd184;
|
||
9'd168: return 9'd210; 9'd169: return 9'd218; 9'd170: return 9'd242; 9'd171: return 9'd250;
|
||
9'd172: return 9'd146; 9'd173: return 9'd154; 9'd174: return 9'd178; 9'd175: return 9'd186;
|
||
9'd176: return 9'd212; 9'd177: return 9'd220; 9'd178: return 9'd244; 9'd179: return 9'd252;
|
||
9'd180: return 9'd148; 9'd181: return 9'd156; 9'd182: return 9'd180; 9'd183: return 9'd188;
|
||
9'd184: return 9'd214; 9'd185: return 9'd222; 9'd186: return 9'd246; 9'd187: return 9'd254;
|
||
9'd188: return 9'd150; 9'd189: return 9'd158; 9'd190: return 9'd182; 9'd191: return 9'd190;
|
||
// yb=6: 129 137 161 169 193 201 225 233 131 139 163 171 195 203 227 235
|
||
// 133 141 165 173 197 205 229 237 135 143 167 175 199 207 231 239
|
||
9'd192: return 9'd129; 9'd193: return 9'd137; 9'd194: return 9'd161; 9'd195: return 9'd169;
|
||
9'd196: return 9'd193; 9'd197: return 9'd201; 9'd198: return 9'd225; 9'd199: return 9'd233;
|
||
9'd200: return 9'd131; 9'd201: return 9'd139; 9'd202: return 9'd163; 9'd203: return 9'd171;
|
||
9'd204: return 9'd195; 9'd205: return 9'd203; 9'd206: return 9'd227; 9'd207: return 9'd235;
|
||
9'd208: return 9'd133; 9'd209: return 9'd141; 9'd210: return 9'd165; 9'd211: return 9'd173;
|
||
9'd212: return 9'd197; 9'd213: return 9'd205; 9'd214: return 9'd229; 9'd215: return 9'd237;
|
||
9'd216: return 9'd135; 9'd217: return 9'd143; 9'd218: return 9'd167; 9'd219: return 9'd175;
|
||
9'd220: return 9'd199; 9'd221: return 9'd207; 9'd222: return 9'd231; 9'd223: return 9'd239;
|
||
// yb=7: 145 153 177 185 209 217 241 249 147 155 179 187 211 219 243 251
|
||
// 149 157 181 189 213 221 245 253 151 159 183 191 215 223 247 255
|
||
9'd224: return 9'd145; 9'd225: return 9'd153; 9'd226: return 9'd177; 9'd227: return 9'd185;
|
||
9'd228: return 9'd209; 9'd229: return 9'd217; 9'd230: return 9'd241; 9'd231: return 9'd249;
|
||
9'd232: return 9'd147; 9'd233: return 9'd155; 9'd234: return 9'd179; 9'd235: return 9'd187;
|
||
9'd236: return 9'd211; 9'd237: return 9'd219; 9'd238: return 9'd243; 9'd239: return 9'd251;
|
||
9'd240: return 9'd149; 9'd241: return 9'd157; 9'd242: return 9'd181; 9'd243: return 9'd189;
|
||
9'd244: return 9'd213; 9'd245: return 9'd221; 9'd246: return 9'd245; 9'd247: return 9'd253;
|
||
9'd248: return 9'd151; 9'd249: return 9'd159; 9'd250: return 9'd183; 9'd251: return 9'd191;
|
||
9'd252: return 9'd215; 9'd253: return 9'd223; 9'd254: return 9'd247; 9'd255: return 9'd255;
|
||
// yb=8: 256 264 288 296 320 328 352 360 258 266 290 298 322 330 354 362
|
||
// 260 268 292 300 324 332 356 364 262 270 294 302 326 334 358 366
|
||
9'd256: return 9'd256; 9'd257: return 9'd264; 9'd258: return 9'd288; 9'd259: return 9'd296;
|
||
9'd260: return 9'd320; 9'd261: return 9'd328; 9'd262: return 9'd352; 9'd263: return 9'd360;
|
||
9'd264: return 9'd258; 9'd265: return 9'd266; 9'd266: return 9'd290; 9'd267: return 9'd298;
|
||
9'd268: return 9'd322; 9'd269: return 9'd330; 9'd270: return 9'd354; 9'd271: return 9'd362;
|
||
9'd272: return 9'd260; 9'd273: return 9'd268; 9'd274: return 9'd292; 9'd275: return 9'd300;
|
||
9'd276: return 9'd324; 9'd277: return 9'd332; 9'd278: return 9'd356; 9'd279: return 9'd364;
|
||
9'd280: return 9'd262; 9'd281: return 9'd270; 9'd282: return 9'd294; 9'd283: return 9'd302;
|
||
9'd284: return 9'd326; 9'd285: return 9'd334; 9'd286: return 9'd358; 9'd287: return 9'd366;
|
||
// yb=9: 272 280 304 312 336 344 368 376 274 282 306 314 338 346 370 378
|
||
// 276 284 308 316 340 348 372 380 278 286 310 318 342 350 374 382
|
||
9'd288: return 9'd272; 9'd289: return 9'd280; 9'd290: return 9'd304; 9'd291: return 9'd312;
|
||
9'd292: return 9'd336; 9'd293: return 9'd344; 9'd294: return 9'd368; 9'd295: return 9'd376;
|
||
9'd296: return 9'd274; 9'd297: return 9'd282; 9'd298: return 9'd306; 9'd299: return 9'd314;
|
||
9'd300: return 9'd338; 9'd301: return 9'd346; 9'd302: return 9'd370; 9'd303: return 9'd378;
|
||
9'd304: return 9'd276; 9'd305: return 9'd284; 9'd306: return 9'd308; 9'd307: return 9'd316;
|
||
9'd308: return 9'd340; 9'd309: return 9'd348; 9'd310: return 9'd372; 9'd311: return 9'd380;
|
||
9'd312: return 9'd278; 9'd313: return 9'd286; 9'd314: return 9'd310; 9'd315: return 9'd318;
|
||
9'd316: return 9'd342; 9'd317: return 9'd350; 9'd318: return 9'd374; 9'd319: return 9'd382;
|
||
// yb=10: 321 329 353 361 257 265 289 297 323 331 355 363 259 267 291 299
|
||
// 325 333 357 365 261 269 293 301 327 335 359 367 263 271 295 303
|
||
9'd320: return 9'd321; 9'd321: return 9'd329; 9'd322: return 9'd353; 9'd323: return 9'd361;
|
||
9'd324: return 9'd257; 9'd325: return 9'd265; 9'd326: return 9'd289; 9'd327: return 9'd297;
|
||
9'd328: return 9'd323; 9'd329: return 9'd331; 9'd330: return 9'd355; 9'd331: return 9'd363;
|
||
9'd332: return 9'd259; 9'd333: return 9'd267; 9'd334: return 9'd291; 9'd335: return 9'd299;
|
||
9'd336: return 9'd325; 9'd337: return 9'd333; 9'd338: return 9'd357; 9'd339: return 9'd365;
|
||
9'd340: return 9'd261; 9'd341: return 9'd269; 9'd342: return 9'd293; 9'd343: return 9'd301;
|
||
9'd344: return 9'd327; 9'd345: return 9'd335; 9'd346: return 9'd359; 9'd347: return 9'd367;
|
||
9'd348: return 9'd263; 9'd349: return 9'd271; 9'd350: return 9'd295; 9'd351: return 9'd303;
|
||
// yb=11: 337 345 369 377 273 281 305 313 339 347 371 379 275 283 307 315
|
||
// 341 349 373 381 277 285 309 317 343 351 375 383 279 287 311 319
|
||
9'd352: return 9'd337; 9'd353: return 9'd345; 9'd354: return 9'd369; 9'd355: return 9'd377;
|
||
9'd356: return 9'd273; 9'd357: return 9'd281; 9'd358: return 9'd305; 9'd359: return 9'd313;
|
||
9'd360: return 9'd339; 9'd361: return 9'd347; 9'd362: return 9'd371; 9'd363: return 9'd379;
|
||
9'd364: return 9'd275; 9'd365: return 9'd283; 9'd366: return 9'd307; 9'd367: return 9'd315;
|
||
9'd368: return 9'd341; 9'd369: return 9'd349; 9'd370: return 9'd373; 9'd371: return 9'd381;
|
||
9'd372: return 9'd277; 9'd373: return 9'd285; 9'd374: return 9'd309; 9'd375: return 9'd317;
|
||
9'd376: return 9'd343; 9'd377: return 9'd351; 9'd378: return 9'd375; 9'd379: return 9'd383;
|
||
9'd380: return 9'd279; 9'd381: return 9'd287; 9'd382: return 9'd311; 9'd383: return 9'd319;
|
||
// yb=12: 448 456 480 488 384 392 416 424 450 458 482 490 386 394 418 426
|
||
// 452 460 484 492 388 396 420 428 454 462 486 494 390 398 422 430
|
||
9'd384: return 9'd448; 9'd385: return 9'd456; 9'd386: return 9'd480; 9'd387: return 9'd488;
|
||
9'd388: return 9'd384; 9'd389: return 9'd392; 9'd390: return 9'd416; 9'd391: return 9'd424;
|
||
9'd392: return 9'd450; 9'd393: return 9'd458; 9'd394: return 9'd482; 9'd395: return 9'd490;
|
||
9'd396: return 9'd386; 9'd397: return 9'd394; 9'd398: return 9'd418; 9'd399: return 9'd426;
|
||
9'd400: return 9'd452; 9'd401: return 9'd460; 9'd402: return 9'd484; 9'd403: return 9'd492;
|
||
9'd404: return 9'd388; 9'd405: return 9'd396; 9'd406: return 9'd420; 9'd407: return 9'd428;
|
||
9'd408: return 9'd454; 9'd409: return 9'd462; 9'd410: return 9'd486; 9'd411: return 9'd494;
|
||
9'd412: return 9'd390; 9'd413: return 9'd398; 9'd414: return 9'd422; 9'd415: return 9'd430;
|
||
// yb=13: 464 472 496 504 400 408 432 440 466 474 498 506 402 410 434 442
|
||
// 468 476 500 508 404 412 436 444 470 478 502 510 406 414 438 446
|
||
9'd416: return 9'd464; 9'd417: return 9'd472; 9'd418: return 9'd496; 9'd419: return 9'd504;
|
||
9'd420: return 9'd400; 9'd421: return 9'd408; 9'd422: return 9'd432; 9'd423: return 9'd440;
|
||
9'd424: return 9'd466; 9'd425: return 9'd474; 9'd426: return 9'd498; 9'd427: return 9'd506;
|
||
9'd428: return 9'd402; 9'd429: return 9'd410; 9'd430: return 9'd434; 9'd431: return 9'd442;
|
||
9'd432: return 9'd468; 9'd433: return 9'd476; 9'd434: return 9'd500; 9'd435: return 9'd508;
|
||
9'd436: return 9'd404; 9'd437: return 9'd412; 9'd438: return 9'd436; 9'd439: return 9'd444;
|
||
9'd440: return 9'd470; 9'd441: return 9'd478; 9'd442: return 9'd502; 9'd443: return 9'd510;
|
||
9'd444: return 9'd406; 9'd445: return 9'd414; 9'd446: return 9'd438; 9'd447: return 9'd446;
|
||
// yb=14: 385 393 417 425 449 457 481 489 387 395 419 427 451 459 483 491
|
||
// 389 397 421 429 453 461 485 493 391 399 423 431 455 463 487 495
|
||
9'd448: return 9'd385; 9'd449: return 9'd393; 9'd450: return 9'd417; 9'd451: return 9'd425;
|
||
9'd452: return 9'd449; 9'd453: return 9'd457; 9'd454: return 9'd481; 9'd455: return 9'd489;
|
||
9'd456: return 9'd387; 9'd457: return 9'd395; 9'd458: return 9'd419; 9'd459: return 9'd427;
|
||
9'd460: return 9'd451; 9'd461: return 9'd459; 9'd462: return 9'd483; 9'd463: return 9'd491;
|
||
9'd464: return 9'd389; 9'd465: return 9'd397; 9'd466: return 9'd421; 9'd467: return 9'd429;
|
||
9'd468: return 9'd453; 9'd469: return 9'd461; 9'd470: return 9'd485; 9'd471: return 9'd493;
|
||
9'd472: return 9'd391; 9'd473: return 9'd399; 9'd474: return 9'd423; 9'd475: return 9'd431;
|
||
9'd476: return 9'd455; 9'd477: return 9'd463; 9'd478: return 9'd487; 9'd479: return 9'd495;
|
||
// yb=15: 401 409 433 441 465 473 497 505 403 411 435 443 467 475 499 507
|
||
// 405 413 437 445 469 477 501 509 407 415 439 447 471 479 503 511
|
||
9'd480: return 9'd401; 9'd481: return 9'd409; 9'd482: return 9'd433; 9'd483: return 9'd441;
|
||
9'd484: return 9'd465; 9'd485: return 9'd473; 9'd486: return 9'd497; 9'd487: return 9'd505;
|
||
9'd488: return 9'd403; 9'd489: return 9'd411; 9'd490: return 9'd435; 9'd491: return 9'd443;
|
||
9'd492: return 9'd467; 9'd493: return 9'd475; 9'd494: return 9'd499; 9'd495: return 9'd507;
|
||
9'd496: return 9'd405; 9'd497: return 9'd413; 9'd498: return 9'd437; 9'd499: return 9'd445;
|
||
9'd500: return 9'd469; 9'd501: return 9'd477; 9'd502: return 9'd501; 9'd503: return 9'd509;
|
||
9'd504: return 9'd407; 9'd505: return 9'd415; 9'd506: return 9'd439; 9'd507: return 9'd447;
|
||
9'd508: return 9'd471; 9'd509: return 9'd479; 9'd510: return 9'd503; default: return 9'd511;
|
||
endcase
|
||
endfunction
|
||
|
||
// Decompose pixel coord into page / block / pixel-in-block.
|
||
logic [11:0] page_x;
|
||
logic [11:0] page_y;
|
||
logic [2:0] by;
|
||
logic [1:0] bx;
|
||
logic [4:0] xb;
|
||
logic [3:0] yb;
|
||
logic [5:0] bw_pg;
|
||
|
||
assign page_x = x >> 7; // x / 128
|
||
assign page_y = y >> 7; // y / 128
|
||
assign by = y[6:4]; // (y % 128) / 16
|
||
assign bx = x[6:5]; // (x % 128) / 32
|
||
assign xb = x[4:0]; // x % 32
|
||
assign yb = y[3:0]; // y % 16
|
||
assign bw_pg = fbw >> 1; // FBW / 2 (FBW must be even)
|
||
|
||
logic [4:0] block_idx;
|
||
assign block_idx = swizzle_psmt4(by, bx);
|
||
|
||
logic [8:0] nibble_idx;
|
||
assign nibble_idx = col_idx_psmt4(yb, xb);
|
||
|
||
logic [31:0] page_base;
|
||
logic [31:0] block_base;
|
||
logic [31:0] page_index;
|
||
assign page_index = ({20'd0, page_y} * {26'd0, bw_pg}) + {20'd0, page_x};
|
||
assign page_base = ({23'd0, fbp} << 11) + (page_index << 13); // FBP*2048 + page_index*8192
|
||
assign block_base = page_base + ({27'd0, block_idx} << 8); // + block_idx*256
|
||
|
||
assign addr = block_base + {23'd0, nibble_idx[8:1]}; // byte_in_block = nibble_idx >> 1
|
||
assign nibble_hi = nibble_idx[0]; // 0=low, 1=high
|
||
|
||
endmodule : gs_swizzle_psmt4_stub
|