// 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