Jump to content
IGNORED

TI-99/4A with a Pipistrello FPGA board


speccery

Recommended Posts

Hi All,

I've been wanting to get involved in the TI-99/4A discussions for a while now, and thought it would be good to do now that I got my messy TI-99/4A hack working.

 

https://hackaday.io/project/13119-ti-994a-memory-extension-with-pipistrello-fpga

 

So I've only got a plain TI-99/4A console, nothing more apart from a few cartridges. I took one cartridge apart and started to use it as a basis for hardware hacking. I put in a socket from a ROM chip and implemented a GROM emulator with a NXP LPC1114 ARM micro controller. I also wired it up to a printed circuit board I made for another TMS9995 computer, to enable page switching of the ROM (initially just 2 pages to get extended basic running, there is 64K of ROM now so I could have 8 pages). The final touch was the addition of a Pipistrello FPGA board, which creates a 32K RAM expansion. This is just the basis to start doing something interesting - these boards combined have pretty significant hardware resources in the TI-99/4A scale.

 

I spent a while debugging the very simple FPGA bus connection, finally I found out there was bug in the schematics of the buffer board I'm using on top of the FPGA for 5V level conversion.

 

To summarise, in addition to creating this mess of wires and boards, the actual creations are:

- GROM emulator with the ARM processor, written in "bare metal" C, i.e. no libraries

- A few lines of VHDL for the CPLD to implement bank switching logic

- A few more lines of VHDL in the FPGA to use a small portion of its resources to create the 32K RAM

 

I hope the writing I put to hackaday explains things in a meaningful way. I hope you guys find this interesting!

 

Erik

  • Like 10
Link to comment
Share on other sites

impressive!

 

There is a project called Spectrum Next (FPGA sinclair spectrum clone) and they are talking about using a Raspberry Pi Zero as the GPU.

 

regards

 

http://www.specnext.com/

 

Thanks and thanks for the link! I was aware of this project, but I have not been following it lately, good opportunity to look back.

On my side I am looking forward to putting more functionality on this FPGA peripheral for the TI. The Pipistrello does have a HDMI output too...

 

Erik

Link to comment
Share on other sites

Now project update at hackaday https://hackaday.io/project/13119-ti-994a-memory-extension-with-pipistrello-fpga

 

As I explain in there, I got the FPGA's memory controller to start working with the 64 megabyte LPDDR SDRAM chip, so my TI now has access to 64 megabytes of memory. This is still very much work in progress, but hopefully interesting. At least I am not aware of any TI 99/4A's with access to more memory...

 

Erik

Link to comment
Share on other sites

Will the FPGA99 project be a TI-99 SOC, or a 9995 based project (as referenced briefly in the github header)?

 

 

***edit***

 

I dug a little deeper. It is the 9995 project. Very interesting stuff there. :)

 

You are a talented fellow!

Edited by Opry99er
  • Like 1
Link to comment
Share on other sites

Thank you! Glad to hear you found this interesting. Just let me know if you've got any questions.

My intention is to keep publishing progress as I make it, and eventually make the project source available once it is at a known good state.

It seems that real life will keep me busy for the coming weekend, but I look forward to advancing this :)

 

Erik

  • Like 2
Link to comment
Share on other sites

Small progress report - I did get the extended Basic ROM integrated into the FPGA along with ROM page selection logic. I also think I have the VHDL code for GROM implementation now done. Memory paging is also already there, but test software not.

I haven't yet had the opportunity to test the GROM implementation as I've been writing code away from home and the hardware. If the GROM bit works then the external hardware is reduced to the FPGA board.

 

Assuming the above works, I will probably next try to create some kind of disk filesystem for the TI. The FPGA board has an SD card slot, so my intention is to implement disk drive support. It seems the technical documents for the TI give a pretty good idea what DSRs need to be written, but does anyone have a starting point? Ideally I'd only need to add SD card handling code to an existing codebase (basically I am hoping I would only need to write routines for sector reading and writing (which I have already done in the context of my TMS9995 project). Code anyone?

 

Erik

  • Like 1
Link to comment
Share on other sites

Small progress report - I did get the extended Basic ROM integrated into the FPGA along with ROM page selection logic. I also think I have the VHDL code for GROM implementation now done. Memory paging is also already there, but test software not.

I haven't yet had the opportunity to test the GROM implementation as I've been writing code away from home and the hardware. If the GROM bit works then the external hardware is reduced to the FPGA board.

 

Assuming the above works, I will probably next try to create some kind of disk filesystem for the TI. The FPGA board has an SD card slot, so my intention is to implement disk drive support. It seems the technical documents for the TI give a pretty good idea what DSRs need to be written, but does anyone have a starting point? Ideally I'd only need to add SD card handling code to an existing codebase (basically I am hoping I would only need to write routines for sector reading and writing (which I have already done in the context of my TMS9995 project). Code anyone?

 

Erik

 

There's a lot of must-read information on Thierry Nouspikel's site. He has a disassembled listing of the TI DSR ROM (>4000 – >5FFF) >here< that should be enlightening.

 

...lee

Link to comment
Share on other sites

A hint on the GROM emulation - if you are doing a full GROM with address readback, make sure to implement the data pre-fetch. It helps a heap in getting the returned address correct. You'll work on 90% of GPL software without it, which makes it a bit of a bear to track down. ;)

Link to comment
Share on other sites

 

There's a lot of must-read information on Thierry Nouspikel's site. He has a disassembled listing of the TI DSR ROM (>4000 – >5FFF) >here< that should be enlightening.

 

...lee

 

Thanks Lee, I am aware of his great site and actually using it for a lot of reference material. I was trying to avoid taking the deep dive of reading that code, but maybe it is unavoidable :)

 

Erik

Link to comment
Share on other sites

A hint on the GROM emulation - if you are doing a full GROM with address readback, make sure to implement the data pre-fetch. It helps a heap in getting the returned address correct. You'll work on 90% of GPL software without it, which makes it a bit of a bear to track down. ;)

 

Thanks Tursi, for now I am only implementing address write and data read. There is no prefetch yet. Like ubergrom (or my similar ARM implementation) I rely on console GROMs for address read back.

I just got this to work partially for the first time - using just the FPGA board - to the point that it displays in the selection screen three (!) options (TI BASIC, Extended basic, and review module library). I suppose it is because my implementation only responds to the first GROM base. Despite it being able to show the menu, it does not really work yet, i.e. choosing option 2 just causes a crash. I am trying to be efficient on the FPGA block RAM use (for GROM emulation), so that instead of using 32K for the 4 extended basic GROMs (with 2K padding) I am using 24K and doing some simple address arithmetic in the VHDL code. The addresses wrap around at >17FF for each GROM (at least in theory). So I guess I either have a bug in GROM selection, or address wrap around - or something else... But hey, at least the name string comes out correctly from the FPGA and it is not colliding with console GROMs!

 

I think I need to again map the GROM to another address and plug back the ARM (working) GROM piece, and do some debugging from extended basic to understand what's not working. Or actually I should try again with Car Wars (which is only 1 GROM - I used that to debug the ARM version).

But that's for tomorrow, today it is getting very late for me in this part of the world...

 

Erik

Link to comment
Share on other sites

Addresses don't wrap at >17FF, that's just where valid data ends. They wrap at >1FFF, like any other ROM, and they wrap inside the same GROM (ie: the top 3 bits are a latch, not part of the address counter). But, any TI released software does not rely on either of those points to work. They jump over the invalid data and they always jump between GROMs. Most of the GROM emulators did not bother with either of those points (thus 8k GROM images exist, not only 6k). I'm not aware of any software that relies on the roll-over behavior going either way, you'd only see it in an assembly read loop as GPL sets the address explicitly for every byte. You probably know this, but the other thing to be aware of is /all/ GROMs respond to /all/ GROM cycles. The only circuit selection is those top three bits, used only to determine whether a GROM returns data for a read data command. They all respond to read cycles and hit the GREADY line, even for reads to other GROMs, and they all latch the current address and count every access, and they all return data for READ ADDRESS commands. So make sure you are playing nice on the bus - GREADY needs to be open collector so you don't force a READY state before other GROMs are ready. :)

 

Beyond that, the system should operate at whatever speed you specify (although it does no good to be faster than other GROMs in the system). Treat GREADY correctly - you should be NOT READY except when you have finished processing a GROM access. (Be that write address, read address, read data, write data!). You need to manage the GREADY line even if you aren't the GROM responding, since it's shared. When GSEL is released, make sure you release the bus as quickly as possible (the console does not wait) and set GREADY back to not ready. I had great fun abusing GREADY to run the system in slow motion. ;)

Link to comment
Share on other sites

Thanks for all those comments. I was already aware of most of the points you mentioned, except the wrap-around not needing to happen at >17FF. That saves some logic. I have my own working microcontroller based GROM (ARM Cortex M0 @ 48MHz) emulation working. It does the wraparound at >17FF, but like you wrote that fact is not really used even if I am now doing it incorrectly instead of letting it just roll over at >1FFF. In the MCU based implementation I am driving GREADY low with a three state buffer pin when the MCU is busy. The MCU handles GROM operations in about one microsecond. The console GROMs drive the GREADY low for about 8 microseconds... Very slow.

With the FPGA I did not bother to drive GREADY at all: I am driving the logic fabric at 100 MHz, and all operations take only a few clock cycles. That, and the fact that I don't have a suitable buffer driver connected to drive the READY signal and I don't want to connect the FPGA directly to the TI bus (it is not 5V tolerant).

I think the most amount of time (40 ns) is spent in the synchronization VHDL code, basically the FPGA waits for WE and DBIN to settle and remain stable for three or four clock cycles before starting operations. So in practice the FPGA is ready in the worst case in something like 50 ns (currently the GROM contents are stored in on-chip block RAM which has very low latency and high bandwidth, all operations on it take just one 100MHz clock cycle or 10ns). The 32K RAM expansion is done in the off-chip SDRAM and that part seems stable. It has a write latency of one clock cycle (due to write FIFOs) and read latency of 14 clock cycles for a burst read; in the worst case when a refresh cycle has just started when read request arrives it takes 28 clock cycles to return read data (I added some small counters for these statistics, they are readable registers so I'm doing extended basic peeks to look at these). Even 28 cycles is not a problem, as it is under 300 ns. So once I get the logic figured out my intention is store ROM and GROM content in the SDRAM. But I need to get things stable first. I suspect the issues I am experiencing right now are still just downright bugs in the logic, or related to glitches. The TI technical manual says that one should wait 100ns for the address bus to be stable after MEMEN/DBIN are asserted, so my problem could also simply be that the synchronization for reads is too short. Writes seem easier, because WE is asserted later in the bus cycle when everything should be stable. Anyway slowing down is always easier than speeding up :) Having said that I am intrigued by the idea of just removing the console GROMs altogether and having the FPGA handle them too, that way GREADY would never be taken low from GROM access. That part obviously would require the capability to read address counter (and implement prefetch), but those are easy once things work otherwise.

 

Nice one on the slow motion stuff - I have to try that too :-D

 

Erik

Link to comment
Share on other sites

Do you have any clue about how much Assembly would be required to take the place of GROM 0 ?

 

Let me get this straight...to use a board that does not have much more memory than the normal TI99/4A the idea is to throw away the entire 30+ year of TI programs for the TI99/4A for this one device?

Link to comment
Share on other sites

Do you have any clue about how much Assembly would be required to take the place of GROM 0 ?

 

Let me get this straight...to use a board that does not have much more memory than the normal TI99/4A the idea is to throw away the entire 30+ year of TI programs for the TI99/4A for this one device?

 

 

I am not sure if I understand your question correctly. My purpose is not to throw away the GROMs, or to be more precise their functionality. I am currently in the process of implementing GROM support in the FPGA, because I think it is a useful capability to have, and also because I don't have many cartridges so I need some platform to run GROM content off, and the current one I have is too complex (if you look at the hackaday page you'll see why). Since I pretty much only have the bare console, nothing else apart from a few cartridges, I decided to implement the functionality you'd normally find in a PEB in an FPGA. It would be cool to have a PEB, but they are not widely available in Europe.

With that background, as I am anyway going to have the capability in the FPGA to support GROM software, I was thinking that I could copy the contents of the console GROMs (all three of them) to the FPGA and remove the GROMs from the console, allowing me to run even the console GROM code at "full speed", basically as fast as the TI's expansion bus runs (which not fast but better than the 8 microsecond cycles with real GROMs). I am thinking the replication of console GROMs on the external device as an experiment, and interested in understanding what the performance benefit might be. From the software point of view nothing would change, things should remain compatible (apart the GROM access cycles being hopefully much faster).

Edited by speccery
  • Like 2
Link to comment
Share on other sites

I posted a small update: https://hackaday.io/project/13119-ti-994a-memory-extension-with-pipistrello-fpga

 

The address auto increment for GROMs was apparently doing increments on its own, due to some glitches most likely. I put in some more signal conditioning, and now the FPGA takes care off all the features I originally did with the multiboard setup. Extended basic seems to run fine now.

Nice one if say so myself, and bedtime for me!

  • Like 5
Link to comment
Share on other sites

This is something I asked on the 32k ram project in one of the other forum threads as well, and perhaps even easier doing with the fpga:

 

Add the possibility to trigger load interrupts via a timer. Would be great for implementing a preemptive task scheduler on the TI-99/4a.

 

 

That's a good idea, I'll add it in. Probably a nice solution would be to have a configurable timer with automatic reload, where one could specify what the interrupt interval could be. I have already been planning to add a 32-bit microsecond resolution counter for general timing purposes (basically a read-only counter). If that same microsecond resolution clock were to drive a-16 bit interrupt timer, one could get a configurable interval between 1us to 65ms. That should be good enough for various purposes?

  • Like 1
Link to comment
Share on other sites

*drools*

 

I am so glad we have so many people in the community doing new stuff like this.

 

Are you just implementing 4K paging ala XB, or are you going to implement 8K paging as well?

 

I have currently two separate paging systems in place: for the module port address range >6000..7FFF there is XB style paging for the upper 4K page. As this is currently done with the on-chip memory of the FPGA there are only two upper pages for a total of 12K which is sufficient for running XB. Apart from that the memory space is divided into 4K pages, in the region where you'd normally have the 32K memory expansion. There are 16384 pages to choose from, or 14-bit page numbers to cover the 64 meg SDRAM memory space. Once I get a little further my intention is to store the module port range to the SDRAM as well, I just first need a mechanism to initialize that memory from somewhere (SD card or the Xilinx configuration Flash ROM). Right now I'm using XB as the debugging tool for this circuitry.

 

BTW I know that this is not "TI approved" behavior, one is not supposed to serve the module port address range from the extension port. The TI technical data manual delightfully says on page 22 about the Cartridge Memory Space: "... The new generation TI console will probably isolate the GROM data bus from the I/O data bus. DON'T TRY TO ACCESS THE CARTRIDGE MEMORY SPACE FROM THE I/O PORT!" So basically I'm not supposed to serve the cartridge address space >6000..>7FFF (and GROMs) from the I/O expansion bus. I think with 30+ years of hindsight we can conclude that the "new generation" TI console is not quite here yet, so I chose not to care :)

  • Like 1
Link to comment
Share on other sites

On the memory use for the 32K space, since you are splitting it into 4K zones already, you might want to take a look at using the switching scheme used by the SAMS card (you would have to extend the latching scheme of the 74LS612 it uses by two bits to use the entire 64MB space though, as it currently maxes out at 16MB). That will keep you compatible with software designed to see that extra space and it will allow you to take advantage of the memory in a seamless fashion.

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