Jump to content
IGNORED

Additional GROM technical details?


brain

Recommended Posts

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

 

 

  • Like 1
Link to comment
Share on other sites

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 by Ksarul
  • Like 1
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • 7 months later...

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

Link to comment
Share on other sites

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 by ralphb
  • Like 1
Link to comment
Share on other sites

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.]

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...