Skip to main content

FPGA Video card

·5 mins

Now that I have two expansion boards working successfully with Y Ddraig, a sound board based on the Yamaha YM2151 and a video board based on the Yamaha V9958 VDP, I’ve been considering the next step to take.

While the V9958 board seems to be working successfully in the limited amount of testing that has been performed so far, it still has the limitation of low resolutions and only capable of generating PAL/NTSC composite or RGB TV signal. There is the V9990 which does have a VGA output, but not for all modes and shares many limitations with the V9958.

I need a video solution with higher resolution modes for text and lower resolution modes for games, ideally with VGA output, while still dated, it still supported by many modern monitors. Existing solutions didn’t meet these needs, so I decided to design my own.

After discussions with Lawrence Manning, who has a working VGA solution on his MAXI000 board, I decided to implement my own video card using a Spartan-6 FPGA. Lawrence is working on a similar solution for his MAXI000, and we are sharing ideas to minimize duplication.

The design uses the Spartan XC6SLX9 in a QFP package, balancing pin count and ease of soldering.

The goal is to have a VDP that works in a similar manner to how the V9958 works. Most of the control of the video will be done through control registers and will allow setting of the screen mode, palette data and some hardware accelerated drawing functions. The board will also allow direct access to the Video RAM by the CPU so that data in RAM can be updated quicker than pushing everything through the registers. Limitations in both the expansion bus and the available pins on the FPGA mean that RAM access with the CPU will have to be banked.

Specifications

  • 2 Megabytes of SRAM as Video RAM
  • VGA output with 4-bits per color (4096 colors)
  • “High-res” 640x480 mode and “game” 320x240 mode (scaled to 640x480)

The above specifications are for the minimum features, but thinking ahead to what else could be achieved. The following feature list are for planned features and could change as development progresses. I want to be able to handle bitmap modes, pattern (tilemap) modes and text modes.

Mode Resolution Colours Bpp Comment
Bitmap 640x480 4096 12 4095 direct colour mode
Bitmap 640x480 256 3-3-2 256 direct colour mode
Bitmap 640x480 256 8 256 colour palette mode
Bitmap 640x480 16 4 16 colour palette mode
Bitmap 320x240 4096 12 4095 direct colour mode
Bitmap 320x240 256 3-3-2 256 direct colour mode
Bitmap 320x240 256 8 256 colour palette mode
Bitmap 320x240 16 4 16 colour palette mode
Pattern 640x480 256 8 256 colour palette mode
Pattern 640x480 16 4 16 colour palette mode
Pattern 320x240 256 8 256 colour palette mode
Pattern 320x240 16 4 16 colour palette mode
Text 640x480 256 8 256 colour palette mode
Text 640x480 16 4 16 colour palette mode

For all modes, maybe with the possible exception of text-based modes, I’m planning to have double buffering and allowed buffer sizes larger than the display area with hardware vertical and horizontal scrolling.

I would like to implement at least 1 hardware sprite in high-res mode but have more available in the game modes which again may only be in the game modes. It would be a nice option to have sprites with an independent palette to the display ,mode. Many of these features will depend on performance and my ability to implement the features so this list may change.

As my VHDL knowledge is limited, just to be able to devlop a system to write a pixel from the CPU and have it displayed on the VGA output would be a good initial target. Also there are some interesting ideas that could be experimented with once everything is up and running. Some of these could be along the lines of per-line palette changes, dual playfields and bit plane mode as on the Amiga.

Expansion Bus Changes

Something that I’ve been considering during the design of the video card is how the expansion bus is currently used.

Currently, each expansion slot has an ID and DATA range. The ID range is 256 bytes wide and the DATA range is 1 Megabyte. The main board has no restrictions on how this is used but on the expansion boards currently developed have the ID line tied to the enable pin of an 74LS541 with a hard coded address to identify the board. When the CPU reads from anywhere in the entire 256 byte range, the ID is placed on the databus. Registers on the YM2151 and V9958 are accessed from within the data range.

Moving forward, the ID range will be used for register access, with the board ID read from the FE-FF address. All other reads/writes to this memory range will be mapped to the device registers. For the existing sound and video boards this will require some changes to the design which I’ve already done. I could have probably modified the boards by hand but took the lazy but simpler route of getting new boards ordered.

On the FPGA card, the register access and the Data access will be separated between the two ranges. The DATA range will be for access to the SRAM. On the existing boards this data area will now be left unused. The bus design was always done as a proof of concept in the initial version, so changes were expected. I think going forward this will provide the most flexible solution.

New boards have been ordered and should arrive soon. The immediate goal is to get basic VGA output working on the FPGA video board, then enable CPU-driven pixel writing to the display. I’ll post updates as development progresses.