kl99 Posted February 4, 2017 Share Posted February 4, 2017 I finally had time to do some more checks of not yet organized stuff. I discovered some Documents that fit here I would say: Grom Technical Document (unknown Source) Grom Technical Document.zip TI-Gram Card Schematics TI-Gram Card.zip Rom-Module Guide (TI internal document, released to TI-GG Usergroup) Rom-Module Guide TI-Internal - Part1of2.zip Rom-Module Guide TI-Internal - Part2of2.zip Feel free to postprocess them and add them to your collections/websites/lists/projects... 1 Quote Link to comment Share on other sites More sharing options...
+Ksarul Posted February 4, 2017 Share Posted February 4, 2017 (edited) The first document was from P.J. van der Bank. The schematics were prepared by Wim Stulen (a great TI guy that I know quite well from BITD). He had (and may still have) a lot of rare and interesting TI documentation that he shared freely. The EPR mentioned in the letter is Eric Paul Rebel, who was a very gifted programmer (look for the four EPR disks to see what I mean). Edited February 4, 2017 by Ksarul 1 Quote Link to comment Share on other sites More sharing options...
speccery Posted February 5, 2017 Share Posted February 5, 2017 I've been too busy working the last several weeks so I'm just now discovering this discussion. It is interesting to note that it seems that everyone who is working to replicate GROM behaviour ends up doing all kinds of trial and error... Personally I found the GROM signal names very unintuitive and confusing (M , MO, GS, GR, GRC - hardly very descriptive nor following typical signal naming conventions). I did GROM implementation trial-and-error cycle twice, first with the ARM microcontroller code and then with VHDL code running on the FPGAs. For what it is worth, in my VHDL code there is a 16-bit "read_addr" register, the most significant byte is returned when address is read. Each address read also copies the low byte of "read_addr" to the high byte of "read_addr". When a new address is written to the GROM module (or a data read occurs), the read_addr register is updated with the new value plus one. Thus there is no prefetch, the address reads just return the current address plus one. Erik Quote Link to comment Share on other sites More sharing options...
brain Posted February 5, 2017 Author Share Posted February 5, 2017 I agree the names are nearly useless. R/!W, !CE, etc. would work much better My code takes a simple approach. As you did, I implemented the 16 bit register, but I hold the actual address in there, not +1. Like you, I don't do prefetch, but an address read reads data from the output of the counter instead of from the register (the counter is tied to the register output at all times). I do have a question, if your register is updated with the address+1, and no prefetch occurs, how do you place the correct address (It would be read_addr-1, I guess) onto the address bus of the memory, so as to get the right value, when a data read occurs? Jim Quote Link to comment Share on other sites More sharing options...
speccery Posted February 6, 2017 Share Posted February 6, 2017 I agree the names are nearly useless. R/!W, !CE, etc. would work much better My code takes a simple approach. As you did, I implemented the 16 bit register, but I hold the actual address in there, not +1. Like you, I don't do prefetch, but an address read reads data from the output of the counter instead of from the register (the counter is tied to the register output at all times). I do have a question, if your register is updated with the address+1, and no prefetch occurs, how do you place the correct address (It would be read_addr-1, I guess) onto the address bus of the memory, so as to get the right value, when a data read occurs? Jim My solution is very similar to yours. The read_addr register that I maintain is just used for the sole purpose of serving address reads. Actual memory accesses use a different register ("offset" in my source code @github). The read_addr is updated on data reads and address writes, so that it always returns the +1. Erik Quote Link to comment Share on other sites More sharing options...
brain Posted February 6, 2017 Author Share Posted February 6, 2017 Sadly, CPLDs are more space constrained, and I could not justify another 16 flops to hold a second register just to service address reads. Good to know how you made it work. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted February 6, 2017 Share Posted February 6, 2017 I realize Tursi (UberGROM) and ralphbb (FinalGROM) have already solved the problem, but I wanted to prove to myself that I could implement a GROM in Verilog. I fought with it all week, and I *JUST* found the error. In short, the docs are wrong :-( The 9900 is big-endian, and the bits are numbered with 0 being the MS-bit instead of the LS-bit. It is something you have to really stay focused on when dealing with TI products from the 99/4A era. In hind-sight the error is obvious, but seeing "least significant byte first" when related to the 99/4A should always raise red flags. There are other GROM docs out there, I have some in hard-copy somewhere in a 99/4A technical reference of sorts created by and for TI's 99/4A technicians. I don't know if there is an electronic copy floating around, I probably got mine on ebay. I'll see if I can dig it up (I have not laid eyes on it in a few years). I'm about to do some FPGA GROM soon emulation as well, so it will be interesting to see what kind of circuit I come up with compared to Tursi's, Speccery's, and your implementations. Quote Link to comment Share on other sites More sharing options...
ralphb Posted September 18, 2017 Share Posted September 18, 2017 I'm currently studying the prefetch mechanism, so I thought I put this here. Although the prefetch should seem clear, I cannot make sense of this program: . li r8, addr movb *r8+, @grmwa nop movb *r8+, @grmwa nop movb *r8+, @grmwa nop movb @grmrd, r1 srl r1, 8 ; print hex value of r1 movb @grmra, r1 swpb r1 movb @grmra, r1 swpb 1 ; print hex value of r1 addr: byte >60, >6F, >20, >30 . Accompanied by this GROM . 00000000 aa 01 00 00 00 00 60 10 00 00 00 00 00 00 00 00 |......`.........| 00000010 00 00 60 1e 09 52 45 41 44 20 54 45 53 54 0f 70 |..`..READ TEST.p| 00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| * 00001000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................| 00001010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f |................| 00001020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f | !"#$%&'()*+,-./| 00001030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f |0123456789:;<=>?| 00001040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f |@ABCDEFGHIJKLMNO| 00001050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f |PQRSTUVWXYZ[\]^_| 00001060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f |`abcdefghijklmno| 00001070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f |pqrstuvwxyz{|}~.| 00001080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f |................| 00001090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f |................| 000010a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af |................| 000010b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf |................| 000010c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf |................| 000010d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df |................| 000010e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef |................| 000010f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ee |................| 00001100 ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee |................| * 00002000. . the program prints >00FF and >7021, both in MESS and on real iron. When you examine the GROM dump, you'll see that there is absolutely no byte of value >FF in region >7xxx. Thus, the read must have been somewhere in >6xxx. Does this make sense, though? My current understanding is that the prefetch happens whenever two bytes are written, where this "counter"/flip flop is reset upon Data Read and Address Read. Thus, address >7021 is perfectly correct, but why is the Data Read so off? Could it use the last "good" address? readodd.zip Quote Link to comment Share on other sites More sharing options...
+mizapf Posted September 18, 2017 Share Posted September 18, 2017 Interesting to see that my GROM emulation seems to be close to the real thing even for unexpected behavior. That is, have you had a look at the GROM code in MAME? https://github.com/mamedev/mame/blob/master/src/devices/machine/tmc0430.cpp If needed, I can guide you through the code. 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted September 18, 2017 Share Posted September 18, 2017 (edited) I confirmed that the byte read is >606F. Thus, when the GROM sees address bytes >60, >6F, it does the prefetch, which means it does read >606F, and then increments the address to >6070. The fact that another address byte is written before the data is read doesn't seem to invalidate the prefetch buffer, so the old value is read. I guess it's logical, but also highly unexpected. Prefetch does indeed mean prefetch. EDIT: added conclusion Edited September 18, 2017 by ralphb 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted September 18, 2017 Share Posted September 18, 2017 There is also auto-increment to deal with. I suspect that, when you wrote the third GROM address byte (>20), that the previous byte had already been incremented to >70. By the time you issued a read address without writing the second byte of the new GROM address, the address read was >7021, which is off by one because of the auto-increment. The correct read address must be decremented by one, so the correct read address is >7020 per the E/A Manual. Also, at this point, the GROM read address is indeterminate (so again says the E/A Manual) and would need to be restored to a known value to do anything useful thereafter. I suspect that, rather than being indeterminate, it is actually >7022, but that may, indeed, not be very useful. Of course the correct address of the byte you read was undoubtedly >606F, as you say, but had you read it without your third GROM write address, it would have reported the read address as >6070 and need the above-mentioned decrement. ...lee [Edits in this color.] 1 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.