JohnPCAE Posted May 17, 2016 Share Posted May 17, 2016 Since about New Year's, I've been cleaning up the SP0256 die shot to make it more of a "logical" view: making all of the various components a single color, minimizing the use of any "extraneous" colors, and generally making the file smaller. This is the first version that has everything cleaned up (no "noise" in the image). It hasn't been checked against the original for correctness, and I could use some extra eyes if anyone has some time to spare. A correct, cleaned-up version would presumably allow a "logical" diagram to follow. Anyway, some features: Lossless .PNG file format (so editing it won't introduce noise into the image) Layers and colors: T : metal (top) B: n- (bottom) P: polysilicon (transistors) R: polysilicon (transistors kept turned on, used as resistive loads -- I think) V: vias T: green B: burgundy T+B: white T+B+V: blue T+B+P: purple T+P: cyan T+B+R: orange T+R: yellow T+B+R+V: red I think that some transistors are larger than others due to conductivity: the larger the transistor, the higher its conductivity, so putting transistors in series necessitates making them larger so the overall conductivity matches the conductivity in alternate paths (I think). I'm a novice at this so take everything I'm saying with a grain of salt. GI_SP0256_die_shot_8500w_10.zip 3 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted May 20, 2016 Author Share Posted May 20, 2016 An update... - Color-coded the power and ground rails - Fixed some minor details - Labeled the pins (yellow text = input, orange text = output) GI_SP0256_die_shot_8500w_11.zip Quote Link to comment Share on other sites More sharing options...
+nanochess Posted May 20, 2016 Share Posted May 20, 2016 A quick look to this beautiful modern art. Thanks John! Quote Link to comment Share on other sites More sharing options...
pimpmaul69 Posted May 20, 2016 Share Posted May 20, 2016 A quick look to this beautiful modern art. Thanks John! GI_SP0256_die_shot_8500w_11.png i would say its a picasso, but picasso was a terrible artist in my opinion and this is a masterpiece! Will have to look around at it more thoroughly when i get the time Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted October 27, 2016 Author Share Posted October 27, 2016 I'm not sure if this is more or less useful, but here is a version with higher contrast and (most) individual lines colorized separately. The intent was to try to make it easier to follow individual traces. GI_SP0256_die_shot_8500w_13.zip 2 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted October 27, 2016 Share Posted October 27, 2016 A quick look to this beautiful modern art. Thanks John! GI_SP0256_die_shot_8500w_11.png Too many colours, not enough cats. If you put a kitten and a funny caption it'll probably go viral. Must try harder. -dZ. 1 Quote Link to comment Share on other sites More sharing options...
+Lathe26 Posted October 27, 2016 Share Posted October 27, 2016 Too many colours, not enough cats. If you put a kitten and a funny caption it'll probably go viral. Must try harder. -dZ. Ask and you shall receive... 1 Quote Link to comment Share on other sites More sharing options...
intvnut Posted October 28, 2016 Share Posted October 28, 2016 (edited) Since this got bumped, I thought I might share some details I worked out back in 2011 when this was decapped. Apologies if it's redundant; I don't remember if I posted it here before. Also, excellent work brightening up the actual traces. Some day I'd love to make a bit-accurate SP0256 emulation. The instruction decoder is the PLA in the lower right. Here's how it decodes the 16 instructions: The PLA above it decodes the number and lengths of the various VTM parameters. I wrote the following C program to decode its contents. Basically, it decodes the LSB of the first significant bit for each VTM parameter across both precision maps, and the number of significant bits. #include <stdio.h> const unsigned char *op_fmt_rom[17] = { "001111001111000011110000", "111100110011000000000000", "001011011010010100001010", "001111001010000011110101", "001011011010010100001010", "001111001010000011110101", "001011011010010100001010", "001111001010000011110101", "001011011011000001011111", "101101100101000001011010", "101101110110000000000101", "101101100111000001010000", "111100110011000000000000", "111100110011000000000000", "111100000000000000000000", "111100000000000000000000", "111111111111000000000000" }; unsigned read_rom(int rmsb, int rlsb) { unsigned out_bit_5 = op_fmt_rom[rlsb][23 - (5*4 + rmsb)] == '1'; unsigned out_bit_4 = op_fmt_rom[rlsb][23 - (4*4 + rmsb)] == '1'; unsigned out_bit_3 = op_fmt_rom[rlsb][23 - (3*4 + rmsb)] == '1'; unsigned out_bit_2 = op_fmt_rom[rlsb][23 - (2*4 + rmsb)] == '1'; unsigned out_bit_1 = op_fmt_rom[rlsb][23 - (1*4 + rmsb)] == '1'; unsigned out_bit_0 = op_fmt_rom[rlsb][23 - (0*4 + rmsb)] == '1'; return (out_bit_5 << 5) | (out_bit_4 << 4) | (out_bit_3 << 3) | (out_bit_2 << 2) | (out_bit_1 << 1) | (out_bit_0 << 0); } const char *label[17] = { "Amplitude", "Pitch", "B0", "F0", "B1", "F1", "B2", "F2", "B3", "F3", "B4", "F4", "B5", "F5", "Amplitude Interpolation", "Pitch Interpolation", "All parameters (Load-All instruction)" }; int main() { int rmsb, rlsb; for (rmsb = 0; rmsb < 4; rmsb++) { printf("%s update, %s precision\n", rmsb & 2 ? "Delta" : "Absolute", rmsb & 1 ? "High" : "Low"); printf("Param# Length 1st LSB Parameter\n"); for (rlsb = 0; rlsb < 17; rlsb++) { unsigned dec = read_rom(rmsb, rlsb); printf("%6d %6d %6d %s\n", rlsb, 1 + (dec >> 3), dec & 7, label[rlsb]); } printf("\n"); } return 0; } There's a 16 bit register at the far lower right (going vertically) which keeps track of which of the 16 parameters will be loaded, while a pair of counters between the two PLAs count out the various fields. One counter keeps track of where the first significant bit is, and the other keeps track of how many significant bits are in the coefficient, directly from the table above. The ROM at the upper left is a compressed form of the 7 bit => 9 bit coefficient ROM. This ROM maps 7 bit linear values to 9-bit non-linear values Some of the columns were compressed away as they were trivially computable with logic functions. (Specifically, likely by tying 4-to-1 mux inputs to 1 or 0 as appropriate.) This C program I wrote some years ago demonstrates how to unpack it. It compares it to the qtbl from jzintv, which in turn comes from the GI patent. #include <stdio.h> const char *rom_img_char[24] = { "################................", "###########################.....", "########........########........", "###########................#####", "#################...............", "####....####....####....####....", "####.......########........#####", "###..............###############", "#...............................", "##..##..##..##..##..##..##..##..", "##..###....####....####....####.", "...######........########.......", ".###############................", "#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.", "#.#.#..##..##..##..##..##..##..#", "#..##....####....####....####...", ".#######........########........", "######.#.#.#.#.#.#.#.#.#.#.#.#.#", ".#.#.##..##..##..##..##..##..##.", ".###....####....####....####....", "######.#.#.#.#.#.#.#.#.#.#.#.#.#", ".#..##..##..##..##..##..##..##..", "#...............................", "..#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.", }; unsigned int rom_img[24]; void init_rom_img(void) { int i, j; unsigned bit; for (i = 0; i < 24; i++) { bit = 0; for (j = 0; j < 32; j++) bit = (bit << 1) | (rom_img_char[i][j] == '#' ? 1 : 0); rom_img[i] = bit; } } unsigned get_bit(int row, int col) { return (rom_img[col] >> (row & 0x1F)) & 1; } unsigned output_bit_0(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, 23) : rmsb == 2 ? 1 : rmsb == 1 ? 1 : !get_bit(rlsb, 22); } unsigned output_bit_1(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, 21) : rmsb == 2 ? !get_bit(rlsb, 20) : 0; } unsigned output_bit_2(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, 19) : rmsb == 2 ? !get_bit(rlsb, 18) : rmsb == 1 ? !get_bit(rlsb, 17) : 0; } unsigned output_bit_3(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, 16) : rmsb == 2 ? !get_bit(rlsb, 15) : rmsb == 1 ? !get_bit(rlsb, 14) : !get_bit(rlsb, 13); } unsigned output_bit_4(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, 12) : rmsb == 2 ? !get_bit(rlsb, 11) : rmsb == 1 ? !get_bit(rlsb, 10) : !get_bit(rlsb, 9); } unsigned output_bit_5(int rmsb, int rlsb) { return rmsb == 3 ? !get_bit(rlsb, : rmsb == 2 ? !get_bit(rlsb, 7) : rmsb == 1 ? !get_bit(rlsb, 6) : !get_bit(rlsb, 5); } unsigned output_bit_6(int rmsb, int rlsb) { return rmsb == 3 ? 1 : rmsb == 2 ? !get_bit(rlsb, 4) : rmsb == 1 ? !get_bit(rlsb, 3) : !get_bit(rlsb, 2); } unsigned output_bit_7(int rmsb, int rlsb) { return rmsb == 3 ? 1 : rmsb == 2 ? 1 : rmsb == 1 ? !get_bit(rlsb, 1) : !get_bit(rlsb, 0); } unsigned output_bit_8(int rmsb, int rlsb) { return rmsb == 3 ? 1 : rmsb == 2 ? 1 : rmsb == 1 ? 1 : 0; } unsigned get_coeff(int index) { int rmsb = (index >> 5) & 3; int rlsb = (index & 0x1F) ^ 0x1F; return output_bit_8(rmsb, rlsb) << 8 | output_bit_7(rmsb, rlsb) << 7 | output_bit_6(rmsb, rlsb) << 6 | output_bit_5(rmsb, rlsb) << 5 | output_bit_4(rmsb, rlsb) << 4 | output_bit_3(rmsb, rlsb) << 3 | output_bit_2(rmsb, rlsb) << 2 | output_bit_1(rmsb, rlsb) << 1 | output_bit_0(rmsb, rlsb) << 0; } const unsigned qtbl[128] = { 0, 9, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 113, 121, 129, 137, 145, 153, 161, 169, 177, 185, 193, 201, 209, 217, 225, 233, 241, 249, 257, 265, 273, 281, 289, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409, 413, 417, 421, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, 473, 475, 477, 479, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511 }; int main(void) { int i; init_rom_img(); printf("Decoded ROM:\n"); printf("Idx: Expect Got Match?\n"); for (i = 0; i < 128; i++) { int dec = get_coeff(i); printf("%3d: %3d %3d %c\n", i, qtbl[i], dec, dec == qtbl[i] ? 'Y' : 'n'); } return 0; } The big ROM at the top right interleaves bytes starting at the left and reading rightward. 16 bytes per column, 128 columns. I don't remember the exact interleaving pattern, but I did verify it against the mask ROM image for at least the first several bytes. Edited October 28, 2016 by intvnut 1 Quote Link to comment Share on other sites More sharing options...
intvnut Posted October 28, 2016 Share Posted October 28, 2016 I think that some transistors are larger than others due to conductivity: the larger the transistor, the higher its conductivity, so putting transistors in series necessitates making them larger so the overall conductivity matches the conductivity in alternate paths (I think). I'm a novice at this so take everything I'm saying with a grain of salt. Generally, you need a wider transistor to drive a larger load. Load in this case is the capacitance on the gates of the transistors downstream. The higher the fanout of a gate, the more capacitance it needs to drive. Of course, a wider gate has higher capacitance as an input, so there's a tradeoff. This PDF goes into a lot of detail for CMOS gates: https://www.ece.umd.edu/class/enee359a.S2008/enee359a-sizing.pdf Fortunately for us, we only need to consider the nFETs, as this is NMOS. Also, given the huge wires, series resistance in the wires isn't nearly as much of a factor as it is in submicron technology. IIRC, when I did my 2 micron chip back in college, I only really looked at relative gate sizes and ignored the wires. Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted October 28, 2016 Author Share Posted October 28, 2016 I don't remember the interleaving off the top of my head, but I did have to figure it out to make sure that I got the bits correct. There are some spots in the big ROM where the traces weren't cleaned properly. Quote Link to comment Share on other sites More sharing options...
intvnut Posted October 28, 2016 Share Posted October 28, 2016 I don't remember the interleaving off the top of my head, but I did have to figure it out to make sure that I got the bits correct. There are some spots in the big ROM where the traces weren't cleaned properly. I found the perl script I used to interleave the SP0256 ROM image to match the ROM itself. It's no work of beauty. :-) According to my notes, it takes as input a text file with one byte per line already converted to 1s and 0s. . #!/usr/bin/perl -w my @rom; foreach my $line (<STDIN>) { chomp $line; my @bits = split //, $line; push @rom, [ reverse @bits ]; } my ($i, $j, $k, $m); for ($i = 0; $i < 128; $i++) { print "Row $i\n"; for ($j = 0; $j < 8; $j++) { print "Bit $j: "; $m = ""; for ($k = 0; $k < 16; $k++) { $m .= $rom[$i * 16 + $k]->[$j]; } print $m, "\n"; } print "\n"; } . This outputs sequences like so: . Row 0 Bit 0: 1111101011111111 Bit 1: 1010101011101111 Bit 2: 1110101111101010 Bit 3: 0100010101000001 Bit 4: 1110101010111101 Bit 5: 0001010101010100 Bit 6: 0101010101010110 Bit 7: 0101010101010100 . Note that each "Row" according to my script is one column in the image. Normal RAM/ROM nomenclature calls those rows, while the interleaved structures are called columns. The ROM on the die is effectively rotated 90° CCW. 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted December 2, 2016 Author Share Posted December 2, 2016 Just a little FYI: I contacted visual6502.org and they are going to look into building a simulation based on the images. I mentioned that it would be wonderful if we had die shots of the STIC; the person who responded was enthusiastic about it, but he needs a donor chip to take apart. I don't know if he has contacted anyone here, but there might be opportunity to fully uncover the STIC's internal workings if anyone has a suitable donor they wouldn't mind parting with. If anyone is interested, you can contact them on the visual6502.org site. 1 Quote Link to comment Share on other sites More sharing options...
GenetixJ Posted December 2, 2016 Share Posted December 2, 2016 Intvnut Seeing your code brings me back to my basic days, especially $. But... no $G? Sorry, bad joke ? I found the perl script I used to interleave the SP0256 ROM image to match the ROM itself. It's no work of beauty. :-) According to my notes, it takes as input a text file with one byte per line already converted to 1s and 0s. . #!/usr/bin/perl -w my @rom; foreach my $line (<STDIN>) { chomp $line; my @bits = split //, $line; push @rom, [ reverse @bits ]; } my ($i, $j, $k, $m); for ($i = 0; $i < 128; $i++) { print "Row $i\n"; for ($j = 0; $j < 8; $j++) { print "Bit $j: "; $m = ""; for ($k = 0; $k < 16; $k++) { $m .= $rom[$i * 16 + $k]->[$j]; } print $m, "\n"; } print "\n"; } .This outputs sequences like so: . Row 0 Bit 0: 1111101011111111 Bit 1: 1010101011101111 Bit 2: 1110101111101010 Bit 3: 0100010101000001 Bit 4: 1110101010111101 Bit 5: 0001010101010100 Bit 6: 0101010101010110 Bit 7: 0101010101010100 .Note that each "Row" according to my script is one column in the image. Normal RAM/ROM nomenclature calls those rows, while the interleaved structures are called columns. The ROM on the die is effectively rotated 90° CCW. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.