MDA/CGA/EGA to VGA

Version 2.0 Released

New Schematics

The new schematics for the daughterboard:

New PCB

The new gerber files (version2) are in the files section:

New B.O.M.

Mind the orientation of the resistor arrays as the pin 1 flip between them (look for the square solder pad)

DIP Switches

Dip1 is the closest to the RGBI connector

Dip2 has no effect in EGA inputs

Dip4 only applies when Monochrome Emulation is on

To use a Hercules video card, close DIP1 and DIP2. For a MDA just close DIP1 and leave DIP2 open

The CGA/EGA screen is automatically switched when DIP1 is open.

Scanlines only affect CGA screens and/or EGA low-res.

Output Resolutions

All these resolutions are VGA standard and should be supported for any monitor.

Some LCD monitors will display 720x480@60Hz downscaled to 640x480@60Hz, so we may see scaled pixels. You can try adjusting the CLOCK/PHASE on your monitor settings if they are available. In this case try to leave as little as borders possible.

Photos

New board assembled:

FPGA Source Code:

Use the github for this board: https://github.com/lfantoniosi/mce2vga

Video

New board working:

Version 1.0 - OBSOLETE Use version 2.0 for new batches.

IMPORTANT: RESISTOR FIX! - 10/03/2017

It turned out the voltage divider is not correct to convert 5V to 3.3V, they should be 1K/2K Ohm instead of 1K/1K. So replace the resistors R26, R27, R28, R29, R30, R31, R32 and R33 for a 2K Ohm 5% 1/4 Watt.

Some boards are presenting a colour separation when switching fast from Yellow to Blue, for example. This resistor fix should fix most of them. I have an EGA card that still shows black pixels around yellow in yellow/blue transition, like text screen. I need to investigate more but it looks these boards have a lower voltage or the transition from 0V to 5V is too slow (or they have some old capacitor failing). This problem does not occur for every pixel but when switching all 4 channels like Yellow RGBI(1101) to Blue RGBI(0010). Looks like the board will capture the switch from 0 to 1 as black in the very adjacent pixel. Does not happen for every yellow/blue pixel, there is some pattern involved. These boards don't have a 6845 but some VLSI chip on them.

--

The FPGA Video Converter

Following the design of the RGB2VGA, I decided to develop a MDA/CGA/EGA to VGA converter. There are some options in the market like the infamous GBS-8200 but I think they are just not good enough. And since these signals are all digital, the design will be much more simpler. 

The FPGA of choice

For this project we will need a FPGA that is able to generate multiple PLLs and have some RAM bits to store the lines. We will need an external Static RAM as the EGA video demans 640x480x6 bits in total.

I have chosen a cheap and available development board called CoreEP4CE6. You can buy it on eBay for 25 dollars and it comes with the FGPA, clock, EPCS and some LEDS and buttons:

To program this board you will need a USB Blaster II, you can find it on eBay for cheap. Some vendors sell this board already with a USB Blaster.

Daughter Board

We will need to develop a daughter board to connect and make few things for use:

Understanding the Signals

These formats use the same 9-pin DB-9F connector at the end of the video card. The 3 formats share the same HSYNC, VSYNC and GND pins (MDA and CGA has an extra GND as pin-2). So they will vary only regarding to the RGB colours and intensity pins. This can be easily wired inside the FPGA code.

The job of the FPGA converter is to listen the signals, create a frame buffer and output it as VGA. Why a frame buffer and not direct conversion ? Because this is not possible due to the clock timings and frame rates. MDA/Hercules is 50 Hz, CGA and EGA are 60Hz, but as CGA has 200 lines, EGA has 350. We will be using similar resolutions on a VGA monitor and the frequency is different.

Supported Video Formats

Hercules Cards are similar to MDA but they use a 16.000Mhz pixel clock

How Does a Converter Work ?

Building a video converter is not a trivial thing, but with some experience you can build one. Basic the idea is to capture the all the signals, store the information locally and generate a new output with them. The vertical sync tells us when a new frame start, and the horizontal sync tells us when a new line start. With this information we can recreate the scan lines using the RGB or the Video signal. There are two ways to do it: Line Converter and Frame Buffer Converter.

Line Converters

Line converters are more restricted converters because the video output must be somehow in sync with the input. Only one scanline is captured, stored and reproduced, one at a time. For example a NTSC video to VGA would be possible because the VGA horizontal frequency: 31.5Khz is exactly the double of the NTSC: 15.75Khz. For each line captured they are reproduced twice in high speed. The advantage of this type of converter is the low latency: only one line is captured so the delay is minimal with almost no lag at all. This would work for a direct CGA converter but not for MDA and EGA, and it a little tricky to make the sync work perfectly as the clocks are never 100% in sync. 

Framebuffer Converters

These type of converters will store one (or more) frames in memory and output them at the desired format. The advantages if that this type of converter can allow different frame rates conversion like 50Hz to 60Hz but they add some lag due to the full screen capture. We will be building this type of converter:

Sampling Frequency

The pixel clock for EGA/MDA is 16.257Mhz. For Hercules is 16.000Mhz and for CGA is 14.318Mhz. According the the Nyquist Theorem the sampling rate should be at least the double of highest frequency. In my tests with FPGA it showed me that I needed at least 4x to remove Jitter completely. For noise reduction (and Hercules fix) I needed 8x. So the board works at the speeds of 130 Mhz and 114.54Mhz. This is good because the SRAM modules needs to move rows in and out very fast. It runs at the CGA clock speed of 114.545Mhz. Hence the needed for a 8 ns SRAM.

To reduce noise I sample the same value several times and use an integrator to decide its value. Noise is particular bad for sync signals. You can see in the sync detectors long samplings waits.

Daughterboard

The schematics for the daughterboard:

The gerber files can be found at the downloads section at the bottom of the screen. For small PCB boards like this I use the AllPCB which is fast and cheap. And the quality is very good for the price.

3D View

B.O.M.

All these components except for the SRAM are pretty simple. I'm using 1K resistor for everything except the V and H outputs. Follow the markings on the PCB.

The SRAM chip is a TSOP44 you will need flux and a chiseled solder tip for that. Also if you choose a different SRAM vendor it MUST BE 8ns or less. 10ns will not work and cause jitter. The SRAM module works at 115 Mhz. We need to pump rows in and out very fast!

Assembled Daugherboard

This is the prototype board assembled:

 I forgot to add the ceramic capacitor filters. The gerbers in the files section are already correct:

With the FGPA core on:

DIP-Switches

The DIP-switches controls some features, from the 1 to 4 (1 closest to the DB-9 Connector)

Fine Tuning

Some boards require a fine-tuning of the scan pixel center. Set the dip-switch 3 to CLOSED and keep pressing the RESET button on the top of the FPGA unit

FPGA Source Code

The source code can be found on: https://github.com/lfantoniosi/mce2vga/tree/V100. You will need Quartus Prime Lite Edition v 17.0 or greater. Also a USB Blaster is needed to program the board. Programming an FPGA board using the USB Blaster is out of the scope of this page. You can find the Quartus documentation.

Image gallery:

Videos