The 6809 has a synchronous bus transfer mechanism which leads to simple system design but means that the whole system runs at the rate of the slowest devices. Synchronous means that transfers are controlled by a clock and that devices must be able to generate or receive data within a clock period. If a device takes longer than a clock period to respond then the system will not work. All devices in the system are therefore chosen to have similar access times. In a 68000 system access times can vary thus allowing greater flexibility in system design. for example very fast, high-cost memory can be used where access is frequent while cheaper slower memory can be used for infrequently accessed areas. To enable this to work the 68000 has an asynchronous bus.
The asynchronous bus works using two control signals. If we take a memory write cycle as an example; the processor sets R/W low to indicate a write cycle, sets the address on the address bus and the data on the data bus. The AS (address strobe) goes low to indicate valid data on the address bus. The processor then waits for a low signal on DTACK (data transfer acknowledge) which is generated at by the memory device when it has received and latched the data. The processor proceeds on the following clock pulse. A transfer like this can take anything from 4 clock cycles upwards depending on the speed of the memory.
This type of bus arrangement has many advantages in terms of speed but it increases the complexity of the system because there are more control signals and memory has to generate the acknowledge signal. There is also a problem which arises when an invalid address is output i.e. one where no memory is present. In a 6809 system the data lines float high and the value $FF is read. In 68000 system no DTACK will be generated and so the processor will wait indefinitely. Clearly this cannot be allowed to happen and so a 'watchdog' timer must be included which monitors the length of time that elapses before DTACK is generated. If no DTACK appears for, say, 10 ms then a BERR (bus error) signal is sent to the processor. This is effectively an interrupt which has its own restart address and allows the monitor program or operating system to take appropriate action such as generating an error message. Again this makes the system more complex but has the added advantage that this situation is detected where in a 6809 system it would not be.
An E signal is continuously generated by the 68000, which does the same job as the E signal of the 6809. Since 6800 peripherals do not generate DTACK, a 6800-type bus cycle is timed with respect to the E signal instead.
How does the 68000 know when to execute a 6800-type cycle?
Address decoding is used to reserve some memory locations for synchronous devices. When an address in this range is used by the 68000, the address decoder sends a VPA (valid peripheral address) signal to the 68000 which causes it to synchronise with the E signal.
Since the E signal is continuously generated, it can be in any phase with the instruction execution cycle. Therefore, when VPA is asserted, the 68000 waits until the E signal is high and then goes low - marking the start of the E clock cycle.
Thereafter, wait states (SW) are inserted by the 68000 until the end of the E clock cycle, when the 68000 cycle terminates in the usual (asynchronous) way.
The address decoding can be as simple as in the diagram below, where synchronous peripherals are addressed when A23 is high.
The use of a single IRQ interrupt input in 8-bit processors means that several interrupting devices need to share the one interrupt service routine (ISR). There will be a delay while the processor determines which device caused the interrupt (by polling), before the interrupt request is handled.
This delay would be a significant problem in an interrupt-bound system (such as a Unix machine). Therefore, if the processor can be informed which device caused the interrupt, it can go directly to the appropriate ISR.
This could be achieved if many IRQ inputs were provided, but this is extravagant. Instead, an interrupting device could place (on request) a code on the data bus which identifies it as the source of the interrupt and the processor can then go directly to the ISR for this device.
For the 68000, interrupting devices provide a number (from 64 to 255) which is multiplied by 4 and becomes the address (00000100-000003FC, see table below) at which an interrupt vector is stored.
Most 68000-type peripherals have a register in which this vector number can be stored.
Should the system programmer forget to initialise this register, a value of $0F is entered by default (by the internal logic of the peripheral itself) when a RESET is given.
A vector number of $0F maps to the Uninitialised Interrupt Vector TRAP in the table below.
In the example shown, a peripheral device is connected to IRQ5.
When an interrupt is generated by this device, the 74148 priority encoder outputs a value of 5 ("1 0 1") assuming no higher interrupts are active. The 68000 recognises this code on the interrupt pins, IPL0-2.
At the end of the current instruction, the 68000 enters the interrupt acknowledge cycle by placing "1 1 1" on the function code pins and gives the interrupt level to which it is responding on A1-3.
On receiving the IACK signal from the decoder, the peripheral device returns the contents of its interrupt vector register to the 68000.
This allows the 68000 to jump directly to the Interrupt Service Routine for this peripheral device and to service the interrupt.
For devices which cannot generate interrupt vectors (e.g. 6800 synchronous peripherals), the VPA pin is used to signal to the 68000 during an interrupt acknowledge cycle that an autovectored interrupt is required. In other words, the 68000 must provide a different interrupt vector for each of the interrupt levels (1-7) as in the table below.
Exception vector assignments in the 68000 | ||
---|---|---|
Number | Address (hex) | Cause |
0 1 2 4 4 5 6 7 8 9 10 11 12 13 14 15 16-23 24 25 26 27 28 29 30 31 32-47 48-54 55 56-58 59-63 64-255 | 00000000
00000004 00000008 0000000C 00000010 00000014 00000018 0000001C 00000020 00000024 00000028 0000002C 00000030 00000034 00000038 0000003C 00000040 00000060 00000064 00000068 0000006C 00000070 00000074 00000078 0000007C 00000080-000000BC 000000C0-000000D8 000000DC 000000E0-000000E8 000000EC-000000FC 00000100-000003FC | Reset (initial SSP)
Reset (initial PC) Bus error Address error Illegal instructions and BKPT Zero divide CHK2, CHK instructions cpTRAPcc, TRAPcc, TRAPV instructions Privilege violation Trace Unimplemented instruction (line 1010) Unimplemented instruction (line 1111) Unassigned, reserved Coprocessor protocol violation Format error Uninitialized interrupt vector Unassigned, reserved Spurious interrupt Level 1 autovector Level 2 autovector Level 3 autovector Level 4 autovector Level 5 autovector Level 6 autovector Level 7 autovector TRAP #0-15 instructions Floating-point coprocessor errors Unassigned, reserved Memory management unit errors Unassigned, reserved User device interrupts |