SID Bridge

Cortex M3 + FPGA Based SID player

In 2020 I made a SID player based on a Lattice MachXO2 that was connected via SPI to a STM32G4 board running Zephyr.

/img/sid_setup.png

Now I got a Trenz SMF2000 board that has a Microsemi SmartFusion2 that has a Cortex M3 and a FPGA on one chip, so connecting the CPU to the FPGA is a lot easier. Instead of going via SPI from CPU to FPGA, it is possible to use a AHB bus to connect the CPU to the FPGA fabric. The connection from the FPGA to the SID chip still needs the 5 address + 8 data + clk + cs + rw + rst = 17 pins like with the previous setup.

/img/sid_bridge.png

This reduces the amount of hardware a lot, although the comparison isn’t entirely fair, the STM32G4 is a Cortex M4 with more RAM resources on chip, but the SMF2000 board has an extra 8MByte SDRAM chip to compensate for the only 64 kbyte on chip SRAM.

SID player

The actual SID player is pretty much the same as described in my previous post, it is basically a C64 emulator that plays a compiled in C64 SID file. The difference with last time is that now the CPU can simply write to a memory address to access the SID chip, no need to go through a SPI driver, this makes to code a lot easier. To make the hardware design easier the CPU uses 32bit wide access, where the C64/SID only has a 8bit bus. The FPGA wil only send the lower 8 data bits to the SID. the address space is divided in two blocks, the actual SID access space starting at 0xC000 and the register space starting at 0x0000. The SID space just holds the SID registers, with the difference they are 32bit aligned, so SID reg 0x00 is on 0xc000, SID reg 0x01 is on 0xc004, SID reg 0x02 is on 0xc008, etc. etc. The register address space currently only has two register on address 0x0000, where the first bit sets and clears the reset pin of the SID, and on 0x0004 where the frequency divider that is used to tune the SID clock frequency. Another difference with the last version is that Zephyr isn’t used, but instead the auto generated code project that the Microsemi tools offer, that was good enough for this demo.

FPGA

Like the SID player software the FPGA implementation became a lot simpler since there is no need for a SPI slave implementation. It is basically a bridge from the AHB bus to the slower SID CS interface.

/img/sid_player_block_diagram.png

Since the SID needs a ~1MHz clock (see my previous post for more details), the sid_bridge component generates that from the 71MHz AHB clock. The read and write access are then synchronized to that 1 MHz clock, which means the AHB bus must wait until the SID is ready. For the rest it is just a really simple state machine that only handles 32bit single word bus accesses, that are translated to the 8bit SID bus accesses.

8Mbyte SDRAM

The SID player uses a 64kByte RAM buffer to emulate the C64 address space, but the SOC on the SMF2000 only has 64kByte memory, so there would not be any memory left to run the program. So the external 8MByte SDRAM was needed, but that didn’t want to work. There are several posts in the Trenz Forum where people also have problems to get it working. In the end I got it working by using a bit of a different setup than most examples show, by using the CORESDR_AHB bridge instead of the AXI bridge. The biggest difference is that it is mapped to a different address 0x5000_0000 and not to 0xA000_0000, but for the rest it seems to work.

And to test it all lets play a tune (Cantina Band, by Markus Klein) on the SMF2000. There are still some problems with the analog audio part, first of all the SID filters are not working correctly (they might be broken due to all the experimenting I did with this chip) and the power supply is not optimal, the Vdd is only 5V and it should be something like 9 to 12V. But the digital interface works, and it produces sound.

Getting the Source Code

The source code is of course available on GitHub. The SID player m3_sid and the FPGA sid_bridge can be cloned using the following git commands

git clone git://github.com/lowlander/m3_sid.git

and

git clone git://github.com/lowlander/sid_bridge.git


personal  fpga  foss  sid 

See also