Spectranet CPLD

From Spectrum
Revision as of 15:23, 23 December 2007 by Winston (talk | contribs)
Jump to navigation Jump to search

The Spectranet's glue logic is implemented in an Xilinx XC9572 CPLD, which is the modern day ULA. The CPLD will do two major functions:

  • trap execution of certain addresses and certain instructions
  • provide a paging mechanism for the flash and static RAM

Execution trapper overview

Since the Spectrum has no formal method of using peripheral paged ROMs, it's quite common for peripherals to trap the execution of code at certain addresses to page in its own ROM. The general procedure for trapping the CPU executing at a certain address is:

  • Monitor the address bus.
  • Look for an active M1 signal from the CPU, along with MREQ, and an address of interest
  • Page in our memory and page out Spectrum ROM when this condition is true.

The Z80 CPU makes it easy to find out when it's doing an instruction fetch, since MREQ is active to read a memory address, and M1 is active. An MREQ+M1 cycle only occurs during an instruction fetch. The trapper itself largely consists of simple combinatorial logic that causes the page-in flip flop to latch when an address of interest is decoded.

The second method is to trap a particular instruction, rather than execution of a specific address. This is generally done as follows:

  • Monitor the data bus.
  • Look for an M1 cycle, and decode the instruction and operands of interest.
  • Page in our memory.

Trapping instructions may be more complex, for example, to trap a CALL instruction, the CPLD must decode the CALL instruction on the data bus and also the following two bytes to check that this is a CALL to an address that's of interest to us (for example, our code entry point).

We also have to take into account that another peripheral with an execution trapper and paged ROM might be connected to our through port. Bad things tend to happen when two memories are paged in simultaneously. Unfortunately, the lack of a formal paging mechanism means there's no standard way of dealing with this.

The Spectranet's method is to insist that other peripherals should be on its through port. Fortunately, quite a few peripherals lack a through port (such as the DivIDE), and it's the only place to put it when the Spectranet is being used. Others do have through ports, so the user will need to know that the peripheral will have to go behind the Spectranet if it's not aware of the Spectranet's scheme.

For any other ROM to get paged in, an address in the lowert 16K must be being accessed. Other devices absolutely cannot page their ROMs if an address is being accessed that's >16K, or it would conflict with RAM. The Spectranet solution is to implement a 'daisy chain' priority scheme. Other devices that use this daisy can be either before or after the Spectranet on the edge connector. Devices that don't do this must be on the Spectranet's through port. The daisy chain is implemented by routing the A15 line via the CPLD. Normally, A15 is simply passed through unchanged (modulo an unimportant 10ns propagation delay). However, if the Spectranet's memory is paged in, A15OUT is held high. Any peripheral device will therefore see any memory accesses as if they were upper RAM accesses, and keep their ROM paged out. The Spectranet also only conditionally traps certain addresses, to allow traps to "ripple through" the possible chain of peripherals. For example, on RESET, the Spectranet traps because the RESET signal was seen, and address 0x0000 was trapped. When the Spectranet has completed its reset routine, it pages out restarting to address 0x0000. Now A15OUT is released, any downstream device will pick up the execution address of 0x0000, and can also initialize. When it then restarts to 0x0000 to run the Spectrum ROM's reset routine - since the RESET latch in the Spectranet's CPLD is no longer set, the board won't trap and the Spectrum's ROM will start normally.

The A15 daisy chain can be used like this for an arbitrary number of peripheral devices (up to the point that the delay on the A15 line gets too long, which should be more devices than is practical).

Conditional trapping also allows things like NMI to be trapped without causing a trap on a device which unconditionally traps NMI - if NMI on our board is pressed, when execution at 0x0066 is trapped, since A15OUT is held high, the downstream device won't trap an NMI that wasn't intended for the downstream device. Similarly, if NMI is pressed on the downstream device, since our NMI latch isn't set, we'll ignore it - so the NMI will be trapped by the correct device.

Execution trapper - page-ins

In the following diagram, M1 and MREQ from the CPU is active low. CS from the CPLD is active low, and HLDROMCS is active high.

A15OUT and HLDROMCS are activated as soon as M1 + address of interest is seen, but only latched on the falling edge of MREQ.
In the case of a 'glitch' due to the bus not being stable before MREQ, page-in signals are briefly active - however, this is unimportant since the glitch will be gone by the falling edge of MREQ, and memories are only active after MREQ.

The execution trapper pages in when an instruction fetch is detected to the following addresses:

  • 0x0000 - Conditionally, only on a reset condition.
  • 0x0008 - Conditionally, if the RST8EN jumper is closed.
  • 0x0038 - Conditionally, if interrupt acceptance is enabled and the W5100 has raised an interrupt.
  • 0x0066 - Conditionally, only when the NMI button is pressed on our board.

Page-ins are triggered when the following instruction is decoded:

  • CALL 0x3FF8 - 0x3FFF - allowing for a small jump table to access the socket library. Unconditional.

Page-ins for addresses are performed on an "optimistic" basis: HLDROMCS becomes active and A15OUT is held high as soon as M1 is detected active, and the address of interest is on the address bus. M1 goes active half a clock cycle before MREQ goes active. Since the address bus might not yet be stable, the page in isn't yet latched. If the address is still set on the falling edge of MREQ, the page-in is latched. The purpose of this timing scheme is to prevent a glitch on A15OUT, which would occur if it wasn't held high until MREQ became active due to gate propagation delays.

The CALL page-in is a little more complex. If the CALL instruction is detected on the data bus at the end of the M1 cycle, a flip flop is set. If the next bus cycle is a read containing the data 0xF8 to 0xFF, a second flip flop is set (and the CALL flip flop is reset). If the next bus cycle contains 0x3F on the data bus, then the page-in flip flop is set, and the previous is reset (a bit must 'ripple through' the three flip flops for a page in to occur. If any other byte is encountered, the 'ripple' is stopped, and a page in doesn't occur).

Execution trapper - page-outs

Our paged ROM state is unlatched on the trailing edge of the M1 cycle for execution at the address 0x007C.

Unlike the page-in, pageouts are performed at the tail end of the M1 cycle. Page outs occur on the following execution addresses:

  • 0x007C - Unconditional

If the page out address is detected with M1 and MREQ active, on the rising edge of M1, the page-in latch is reset, A15OUT reverts to pass through the A15 signal, and HLDROMCS becomes inactive.