The BBC Micro is a vastly more complicated machine than the Spectrum. It became apparent at a fairly early stage that were would be no pay-back at all until a significant chunk of the logic had been implemented. Just to get the MOS to display the “BBC Computer” message on the screen obviously requires a working CPU and memory system, but also the 6845 CRTC, Video ULA, System 6522 and at least a partial implementation of the keyboard (to read the DIP switches). The SAA5050 was omitted to begin with.
Initially, the keyboard was simulated with just the minimum amount of logic for the MOS to read the DIP switches. The MOS will hang without this, and it was necessary anyway so that one of the bitmapped modes could be selected for startup (no teletext hardware yet).
Once the system was presenting a BASIC prompt in MODE 1 the rest of the keyboard was added. The PS/2 interface from the Spectrum project was re-used, with a modified keymap, and the BBC’s auto-scanning logic was added.
Simple programs could now be entered and run, but there was still no way to load from an external source. The MMBEEB project provides a way for a real BBC to access disk images on an SD card using a connection to the user port and a modified DFS ROM. By connecting the DE1’s SD card slot to the User VIA in the same way that the MMBEEB would, it was found that the SmartMMC ROM would work just fine.
Next to go in was the sound support, since a model of the TI SN76489 was already available. This is accessed via the System VIA’s “slow bus”, and very little effort was required to get it up and running.
The final key feature that was needed was the addition of the SAA5050 teletext chip. There is a clock domain to cross here because the required 6 MHz pixel clock cycles cannot be provided for uniformly from the 32 MHz system clock. Once this was dealt with the rest of the chip is actually quite straightforward.
Read on for some component detail.
The CPU is the T65 core from FPGA Arcade with a bug fix from PACE Dev. Without the bug fix the operation of the “BRK” instruction is incorrect, and results in faulty interrupt handling. The core has a fully synchronous top level with separate input and output buses, in common with all the other components in the design.
Known bugs/limitations: None confirmed but possible remaining interrupt issue?
A 32 MHz master clock is used instead of the real BBC’s 16 MHz one to enable synchronous design, vital for correct operation on an FPGA. The clock is derived from the DE1’s 24 MHz oscillator using one of the Cyclone II PLLs. The 24 MHz input is also used directly by the SAA5050 which needs to derive a 6 MHz dot clock.
A 5-bit counter is used to generate top-level clock enables for various parts of the system, the slowest therefore being the 1 MHz needed for the VIAs and some other peripherals. Cycles are assigned as follows:
The CPU is enabled only during even cycles, while the video hardware and all peripherals are enabled only during odd cycles. This ensures that the correct result is available on the CPU data input in time for the next CPU tick; the 6502 performs one bus cycle for every clock.
Off-chip memories are used for everything in the design apart from the SAA5050 character ROM. The DE1 includes 4MB NOR flash and 512 KB static RAM, as well as an 8 MB SDRAM. The flash and SRAM are used here.
The outputs to the SRAM are registered to ensure that write glitches do not occur. Since this introduces a one-cycle delay, the signals applied to the SRAM are generated out of phase with the enable cycles. This is so that the address generated during the previous cycle is applied and the resulting data available in time for the next cycle.
All of the BBC’s internal peripherals are mapped into a 256 byte page within the MOS address space at 0xFE00. This page is given the name SHEILA, along with two pages at 0xFC00 and 0xFD00 which are called FRED and JIM respectively. These last two are used for expansion.
SHEILA is further sub-divided to allow access to each of the internal peripheral devices at the following addresses. Those highlighted in green are already implemented here:
|0xFE10||Serial ULA (SERPROC)|
|0xFE20||Video ULA (VIDPROC)|
|0xFE30||Paged ROM select latch|
|0xFE40||System VIA (6522)|
|0xFE60||User VIA (6522)|
|0xFE80||Floppy disk controller (8271)|
|0xFEA0||ECONET ADLC (68B54)|
|0xFEC0||Analogue to Digital Converter (uPD7002)|
|0xFEE0||Tube ULA (external)|
All of the peripheral blocks are again fully synchronous and use separate input and output buses. The outputs from each are routed to the CPU through a multiplexer driven by the address decoder.
The MC6845 display controller model was written from scratch to be functionally equivalent to its datasheet description. The model is more or less feature complete – there is no support for the v_total_adjust register, nor for the “skew” features in the interlace mode register. The width of the vertical sync can be adjusted between 1 and 16 lines, which is a feature of the ‘A’ version of the device.
Both interlace scan and interlaced sync+video modes are supported, the latter being required for MODE 7 support. When interlaced mode is selected the vertical sync output is delayed by half a line during odd fields. The resulting video signal is sufficiently close to standard to drive a modern TV even without the v_total_adjust feature. CRT TVs are generally more forgiving and this works fine too.
In the BBC the CRTC clock is provided by the Video ULA at either 1 MHz or 2 MHz depending on the selected mode. Here it is the clock enable that is gated by the ULA, in line with good FPGA design practice.
Known bugs/limitations: No support for v_total_adjust or skew.
The BBC’s Video ULA provides two main functions in generating the bitmapped display modes; serialisation of the pixel data from RAM (the CRTC is a character-based device) and colour generation. Colours can be chosen from a programmable palette, and the number of colours available on screen at a time depends on the selected screen mode. The output from the Video ULA is multiplexed with the output from the Teletext chip and fed to the video DAC.
The ULA presents two write-only 8-bit registers at 0xFE20 (control register) and 0xFE21 (palette register). The control register has the following functions:
|7||Cursor segment 0|
|6||Cursor segment 1|
|5||Cursor segment 2|
|4||CRTC clock select (0 = 1 MHz, 1 = 2 MHz)|
|3:2||Number of columns (pixel clock frequency)|
|1||Teletext mode enable|
|0||Flash bit (inverts output if set, toggled by the MOS)|
The cursor is inserted by the ULA starting from the rising edge of the CRTC’s cursor output. The length and position of the cursor is specified by setting or clearing the cursor segment bits, the correct values being inserted by the MOS as required for the selected screen mode.
Pixel clock frequency can be selected as 16, 8, 4 or 2 MHz and affects the width of a pixel on the screen as well as the number of colours that can be displayed. Some modes require special programming of the palette register to avoid strange effects on screen. More information about this can be found on Beeb Wiki.
There is nothing particularly special about the resulting VHDL model. A pair of counters provide the enables for the CRTC and cursor logic, and the output shift register is loaded from RAM during the cycles after the CRTC was enabled. The palette is stored in an array of 15 4-bit registers.
Known bugs/limitations: No INVERT support (any need for this?)
Teletext (MODE 7) support was added later in the design, and is complete apart from “hold graphics” support (which needs adding) and the character rounding (which probably doesn’t). Features that are not used by the BBC were also not implemented (the SAA5050 includes hardware for decoding a TV remote control, for example).
The SAA5050 uses a 6 MHz pixel clock which can’t be derived from the 32 MHz clock used everywhere else, at least not with an equal amount of time between ticks. To solve this the block runs directly from the 24 MHz input clock with a 4:1 clock enable. Bus accesses are double-registered into the pixel clock domain.
The character and graphic shapes are all stored in ROM. The output shift register is loaded even for control characters, so the corresponding ROM locations are blank to ensure that the display is not affected. The character and graphic shapes are addresses separately in the ROM using an extra bit, but the separated graphics shapes are generated using a mask rather than a separate set of bitmaps.
Control characters and state retained in a set of latches. These are cleared to their default settings at the start of each line, with timing and character addressing provided by the CRTC as normal.
Known bugs/limitations: No “hold graphics”. No support for features not used by the BBC. No character rounding.
Paged ROM Latch
Access to the sideways ROMs is via a 16 KB window at 0x8000 (the MOS ROM is always present at 0xC000). The particular ROM that can be accessed is selected by writing to a latch at 0xFE30. In the original BBC B only the lower two bits are decoded – more slots can be added by decoding all four bits, which is an obvious and simple improvement that could be made.
System and User VIAs
VHDL models of the MOS 6522 VIAs were available from the VIC20 project at FPGA Arcade, so two of these were instantiated for the System and User VIAs. The System VIA handles interrupts from the CRTC and keyboard, and is also responsible for generating the 10 ms OS tick interrupt. The IO ports control various internal functions, some through a TTL latch (which translates directly into VHDL) and some via a “slow bus” formed from port A and some of the latch bits.
The User VIA is the interface to the printer and user ports, the latter of which is required for the “MMBEEB” SD card interface. The DE1’s SD card pins were routed directly to the User VIA signals corresponding with the required user port connections.
MMBEEB’s use of the 6522 shift register highlighted a bug in the VHDL which initially prevented it from working. The 6522 datasheet states that the shift register is disabled in mode 0, and the FPGA Arcade implementation works in this way. However, the BBC Advanced User Guide states that, although no interrupts are generated in this mode, shifts do still occur on each rising edge of CB1, and the value on CB2 is shifted into the least significant bit. MMBEEB relies on this behaviour and the 6522 model has been corrected accordingly.
Known bugs/limitations: None known.
SN76489 Sound Generator
Also written through the System VIA’s “slow bus” is a Texas Instruments SN76489 Programmable Sound Generator. Once again, the heavy lifting had already been done on this by the FPGA Arcade guys, and Armin Laeuger’s implementation dropped more or less straight in. The block produces an 8-bit signed output which requires further processing if it is to be output through the DE1’s audio codec.
The codec, a Wolfson WM8731, is an I2S device with flexible mixer capabilities that can be programmed over an I2C bus. Further registers are provided for configuring the digital filters for the sample rate at which it is operating. To load the codec registers the I2C state machine that was originally written for the Spectrum project was reused. The configuration is hard-coded and selects unity levels for input and output, 16-bit standard I2S input for the PCM audio, and an 8 kHz sample rate with a 24 MHz master clock. The state machine simply pushes the pre-set register values into the codec when the system is reset.
The I2S audio path was also reused from the Spectrum. This block is a bidirectional serial-to-parallel converter with some additional logic to handle the I2S framing. In this case only the output part is used – the 8-bit audio from the 76489 drives the most significant byte of both left and right channel. The sound generator and codec are running asynchronously, but in practice this doesn’t seem to lead to any audible artifacts.
Known bugs/limitations: Occasional spurious tones – suspect the bug is actually elsewhere, though.
Support for the DE1’s PS/2 keyboard interface was re-used from the Spectrum project. The PS/2 decoder sends press/release scan codes to a block of logic containing an array of registers. These registers are arrange internally in the same row and column matrix as the real BBC’s keyboard, and pressing or releasing a key sets or clears the corresponding register in the matrix.
In the real Beeb the BREAK key is simply a reset switch. The System VIA has its own reset circuit which is triggered only on power-up, and this is used by the MOS to detect whether or not a reset was hard or soft. In the FPGA version the BREAK output is generated by the keyboard decoder and is used in the same way. Additionally, though, the keyboard logic itself is placed in the System VIA’s reset domain to ensure correct operation.
The auto-scanning logic found on the real BBC’s keyboard PCB is required for correct interrupt handling. This is implemented here as part of the keyboard matrix decoder block, and is essentially the same as the original hardware.
Known bugs: None known.
During development there were a number of occasions where the machine would hang with no useful output, usually due to spurious interrupts. To aid debugging a hardware breakpoint and watchpoint unit was added. This has been left in-circuit in the release version, and may be of interest as a standalone block.
The debugger drives the 4-digit display and a couple of LEDs to indicate the selected mode. All four of the buttons are used to control:
- KEY(3) – Single step
- KEY(2) – Display mode
- KEY(1) – Display digit
- KEY(0) – Digit adjust
Switch 8 is used to select between RUN (up) and HALT/STEP (down).
Pressing the display mode button cycles the display through current instruction address, breakpoint address, watchpoint address and auxiliary input. The auxiliary input is an additional 16-bit bus that can be fed from external logic as required. In breakpoint and watchpoint modes the address can be edited using KEY(1) to select the digit (which will flash) and KEY(0) to alter its value.
When halt mode is entered the CPU is stopped by gating off its clock enable. A halt is triggered by the debugger when either an instruction fetch occurs from the breakpoint address, or a data write occurs at the watchpoint address. It can also be entered manually using the RUN/HALT switch. Pressing the single step button resumes from a breakpoint or watchpoint halt when in run mode, or single-steps in halt/step mode. Single stepping from a breakpoint is possible by selecting halt/step mode after the breakpoint hit.
CPU interrupts are gated off in halt/step mode.
Bugs and Enhancements
As well as ironing out the bug that prevents Manic Miner from running, there are plenty of areas in which the project can be continued. From the standard BBC B system the disk controller, Econet, serial/cassette interface and the analogue to digital converter are currently unimplemented. This is probably the order in which I would consider adding these missing peripherals. In particular the disk interface would be a nice feature assuming I could lay my hands on a still functional drive!
Both the 1 MHz bus and the Tube should be fairly trivial to add, given enough physical pins on the DE1’s two expansion headers. The biggest issue here will be making the timing close enough to the real thing to keep the peripherals happy.
The following blocks are used in the design, with modifications specified above where required.
- T65 6502 with fix for BRK bug from https://svn.pacedev.net/repos/pace/sw/src/component/cpu/t65/
- MOS 6522 (VIA) by MikeJ from http://www.fpgaarcade.com/vic20_main.htm
- TI SN76489 (sound) by Armin Laeuger from http://www.fpgaarcade.com/library.htm