I have finally solved the issue with holding multiple FPGA designs inside a single configuration flash. It seems there is a special tool just for the purpose of creating complex program files (.pof files). The details are buried in this document. So this is great news, though since I only have one PLCC84 adapter made up I won't be able to test the theory until I have the MAXI09 board in my hands.
Another mystery I've solved this past week is how to handle system resets. Since these FPGAs must receive their design from the flashes at start-up, it is not possible for the MPU to simply be bought out of reset by a reset generator, as was done when the glue logic was handled by a CPLD. If this was done there would be a race at start-up between the reset generator and the FPGA configuration process. If the reset generator took the MPU out of reset before the FPGA was programmed, the computer would not start because vital pins, like memory chip selects, would not yet be operating. Whilst it's likely that the FPGA would win this race and be programmed in time, it isn't good practice to leave any uncertainty in circuit design.
The solution I've come up with for this problem is to use the FPGA itself to generate a system reset signal and dispense with the old DS1813 (PDF) reset generator entirely. The FLEX 10K has two useful signals for this task:
- CONF_DONE: This signal is principally used to control the configuration flash. It indicates, by going high, that the configuration step is complete, that is to say it has received the design from the flash. By itself this can't be used to generate a system reset because after the configuration phase, the FPGA must then initialise, which takes a few more microseconds.
- INIT_DONE: This is an optional signal, meaning the same pin can also be used for IO, that indicates, by tristating, that the FPGA has entered the running phase and is now implementing the design. Because it is also an IO pin, and the FPGA receives the instruction for how to use the pin as part of the configuration data, this pin is, as all the IO pins are, tristated at start-up, before any configuration data has been received.
These two signals can be combined, by ANDing them, to form a useful /RESET signal, as the following screenshot from the logic analyser shows:
In this screenshot, the system was first powered up from cold, and then immediately after the MPU came out of reset, it was reset again by pressing the nCONFIG button (described below). Whilst it looks like CONF_DONE and INIT_DONE rise at the same time, zooming in shows CONF_DONE falls about half a uS seconds before INIT_DONE. The result of ANDing the two signals results in a signal that remains low until the point where initialisation is complete. To be fair, I suspect my 6809 is slow enough that simply using CONF_DONE as /RESET would do the trick. But I am trying to do a good job here, not just something that works.
One further consideration is how to reset the computer without cycling the power. Reading the FPGA documents once more shows a nice simple solution to this: shorting the nCONFIG pin to ground, and then letting the pin float high via its pullup, causes the programming process to be restarted. A simplified schematic of the programming lines, reset logic, and button is as follows:
In this diagram the JTAG chain has been omitted for clarity. I have jury-rigged this setup by performing some surgery on the existing CPLD board, removing the reset generator and tieing the /RESET line to a quad, two input AND gate 74HC08 (PDF). The inputs of this AND gate, at the top of the breadboards, is attached to the CONF_ and INIT_DONE signals. A button for nCONFIG completes the new reset handling:
It is difficult to see in the picture the red wire snaking it's way to the 6809 board is the /RESET signal. The nCONFIG push button is at the bottom left of the breadboard.
This seems to work very nicely, though I am slightly disappointed that I will need to use some discreet logic. Pressing the reset button causes the FPGA to obtain its configuration again, with the MPU resetting a few uS later. And of course the MPU is held in reset whilst the FPGA starts up at power-on too.
One additional bit of surgery was performed: the sliding switch which is used to halt the processor was removed and the /HALT pin connected to a pin on the FPGA. This is the pink wire leading to the 6809 board in the in the picture above. This allowed me to verify, at least somewhat, that my ideas for halting the MPU during DMA transfers were viable.
Since only a handful of the required signals were available to the FPGA I was not able to actually implemented a DMA controller. But borrowing the VHDL implemented for the time-limited buzzer output I was able to pause the processor for a variable amount of time by writing to the buzzer registers from the monitor. The previously internal signal, SOUNDPLAYING, was inverted and routed externally to the /HALT pin on the 6809. By watching the BA and BS LEDs I was able to verify that the processor was halted, and then un-halted. This does not fully confirm that the DMAC is certain to work, but it is a major source of encouragement.
The last major issue regarding use of an FPGA to perform glue logic functions relates to the fact that, at least with the FLEX 10K, all of the IO pins are tristated whilst the FPGA is being programmed. This a problem because these pins are used to drive pins like Chip Selects and Output Enables on the various memory and peripheral ICs. This leaves these pins to float for a brief time during start-up. This is a problem for two reasons.
The biggest problem is that if /CS and /OE pins float low, then the data busses on these ICs will be in the read state, which will cause the bus to come out of tristate and be driven. This could happen to multiple ICs at the same time, causing bus contention. Whilst the MPU is not running at this time, it's possible that the multiple busses being driven against each other will cause excessive current draw.
Likewise, whilst floating, a CMOS input's voltage level can sit between the high and low thresholds. A CMOS input shunts current from Vcc to ground at the moment of transition between high and low. On a square edge this is inconsequential. But an input sitting around the cross over window, which could happen with a floating input, can also cause excessive current.
The solution in both cases is to connect these FPGA outputs to a pullup resistor. That way when the FPGA has tristated the output pin during start-up the memory Output Enable (or other) will see a voltage very close to Vcc, which for an /OE will force the memory IC off the data bus regardless of the other control pins.
After consulting the folks on the 6502 forum I have concluded that the problem of excessive current draw caused by inputs floating around the grey zone between high and low is less of a problem then I first feared. None the less, since some peripheral ICs do not have a read line generated from the FPGA (eg. the 6522, which uses the MPU's R/W line) I will put pull-ups on all the Chip Select lines. This is the only way to guarantee that these IC won't start to drive the data bus.
I have to say that these pull-ups are a little annoying, and the computer may well work without them. But none the less I would rather do things properly.
I'm now at a point where I can draw up a schematic for the FPGA section of the MAXI09:
This is still very much a draft since at a minimum I need to allocate component numbers to each part. Also, the pullups on the /CSn pins, and other critical pins have not yet been added. There will likely be other changes as well. There are a few differences to what I described previously.
Obviously the /RESET handling is different, since it is generated by the FPGAs control signals not as an output pin. I have also discovered that the SC16C654 QUART, in 68 mode, has an ordinary active low reset pin, which means an active high reset does not need to be generated. This puts me two pins up, and one pin down (for INIT_DONE) on the previous MuDdy allocation, giving me another Chip Select. DISCo makes use of the DEV_CLRn pin to implement a /RESET signal, which will clear all registered flip-flops to 0 when asserted
I have decided to use a DAC attached to the MPU bus, instead of it being attached to DISCo. In its place will be the buzzer output. I can still experiment with sound generation from an FPGA using an expansion board. This frees up 7 pins, allowing me to route /NMI as a regular interrupt, with a push button input pin as well. Since I need INIT_DONE from DISCo as well as MuDdy, this leaves me with four currently unused IO pins. Curiously this is just enough pins to hook up an SD card via SPI, such that I could implement a sort of SD card host controller (as opposed to a simple SPI bus interface which the 65SPI/B provides). This would require a great deal of logic resources though. Plus it leaves me with the feeling that SD cards are not very retro. We will see.
On the Configuration Flash IC two pullups are not required since I have found out that the EPC2 (PDF) can be configured to use it's own internal pullups.
I'm currently in the middle of making up the breadboard for the AD724 (PDF) (not 725, oops) RGB to composite converter. I also have yet to order the AD8013 video amplifier ICs. These will be needed soon so I can confirm the function of the analogue portion of the video output. After that, the only remaining task, schematic wise at least, is to settle on a DAC, and its audio amplifier.
Talking of things analogue, another thing I'm in the middle of is choosing which Digital Storage Osciliscope to purchase. So much choice, not made any easier by me not knowing what it is I really need..