FPGA VGA Controller for 8-bit computer - Page 1
Forum section: electronics / general

author: nockieboy
author_rank: Super Contributor
timestamp: October 16, 2019, 01:42:20 pm
content: Hi all,Don't know if anyone has noticed, but Grant Searle's website (http://searle.hostei.com/grant/z80/) seems to have blinked out of existence.This poses a problem for me as I didn't download the code or related material for his FPGA Multicomp design. I'm now thinking about my first foray into FPGAs by creating a VGA driver for my DIY computer, but it seems a big 'leg up' has now disappeared from the interweb.Does anyone have the code for the Multicomp? I was hoping to sift through it and either adapt or just learn from Grant's implementation of the graphics driver in VHDL.For clarity, I've got an Altera Cyclone II EP2C5 which I was hoping to use to make a VGA controller, either with enough on-board RAM (or a discrete SRAM memory chip) for a frame buffer in the region of 128 KB, to allow a resolution of (up to) 640x480 with two colours, or down to 160x120 with 256 colours and double-buffering.I've since ordered a Xilinx Spartan 6 as well, thinking it might be even more overpowered for the job.I've seen designs where the controller outputs an RGB signal directly to the VGA connector via resistors, and others where the controller passes data from the frame buffer to a video DAC. Bearing in mind I'm using 8-bit data (so a maximum of 256 colours unless I start doubling-up on bytes-per-pixel in the frame buffer), the DACs I've seen seem to expect a lot more bits on their inputs...I'm also wondering about how best to interface to the Z80 computer, too. Would it be best to send data to the VGA controller via IO calls and let the VGA controller handle the frame buffer? I'm not a fan of restricting the Z80's access to memory for 75% of its runtime whilst the VGA controller reads from a frame buffer in the Z80's memory space, and dual-port RAM is too expensive for my needs.Any thoughts, comments etc. appreciated! I'm not very experienced at this stuff having spent the last two years learning electronics by building a DIY Z80-based computer...EDIT:For anyone interested, this topic evolved into a fully developed video card using the EP4CE10 FPGA from Altera. The github for this project is here:https://github.com/nockieboy/gpu

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 16, 2019, 01:54:57 pm
content: Does this contain what you need?https://github.com/wsoltys/multicomp

author: nockieboy
author_rank: Super Contributor
timestamp: October 16, 2019, 02:55:18 pm
content: Quote from: SiliconWizard on October 16, 2019, 01:54:57 pmAh yes, thanks SiliconWizard!That gives me a fair starting point to work from, I think. As I'm only going to be building the video driver circuit, hopefully I'll be able to make use of some more RAM space. Will have to go start on some VHDL/FPGA tutorials as I'm starting from scratch with them.

author: dferyance
author_rank: Regular Contributor
timestamp: October 16, 2019, 05:43:02 pm
content: Just a few thoughts / ideas.The resistor ladder dacs are popular and mostly work fine. However I have run into their limitations in my own work. I've been doing VGA with 256 color, but a palette system out of 24-bit color. I often see obvious color differences due to the limited number of bits in the resistor ladder. If you can live with this, they work great and are simple. It sounds like you are doing 256 bit color without a palette so you should be fine, but if you extend it latter this is a limitation you will run into.For interfacing the two, do you need framebuffer-level access? For example, the original gameduino outputs VGA but takes in different drawing commands (over SPI). This way you aren't having read and transmit entire framebuffers over a slow bus.

author: NorthGuy
author_rank: Super Contributor
timestamp: October 16, 2019, 08:10:33 pm
content: Why VGA? It would be more natural to go digital.

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: October 16, 2019, 08:27:06 pm
content: Quote from: NorthGuy on October 16, 2019, 08:10:33 pmGot a back-of-napkin design for that?

author: kizmit99
author_rank: Regular Contributor
timestamp: October 16, 2019, 09:14:56 pm
content: Quote from: jhpadjustable on October 16, 2019, 08:27:06 pmThe CylconeII OP mentioned supports 3.3V LVDS outputs which can (pretty easily) be used to drive an HDMI monitor. The resolutions OP mentioned would have pixel clocks below the HDMI minimums, so would require pixel replication to get into the supported rates. But I suspect that some quick math would find something acceptable without blowing past the output speed limit on the FPGA.Both of these are useful examples:http://hamsterworks.co.nz/mediawiki/index.php/Minimal_HDMIhttps://www.fpga4fun.com/HDMI.html

author: Canis Dirus Leidy
author_rank: Regular Contributor
timestamp: October 16, 2019, 11:00:09 pm
content: Quote from: jhpadjustable on October 16, 2019, 08:27:06 pmThere were several examples at marsohod.org (in Russian):Connecting MAXII (EPM240) to a LCD panel with a parallel RGB interfaceDriving LVDS interface with MAXII(dirty hack, due to lack of PLL in EPM240, but works).DIY framebuffer (from old SDRAM) for DIY photoframeHDMI interface with MAX10P.S. Also look for "Circuit Design and Simulation with VHDL". In particular, chapters 16 "VHDL Design of DVI Video Interfaces" and 17 "VHDL Design of FPD-Link Video Interfaces".

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: October 16, 2019, 11:35:23 pm
content: Well. I learned something today! I had preferred the VGA idea because it's more "tangible" and offers easier-to-read feedback in case of errors, but if it'sthat easy, objection withdrawn.

author: Codex
author_rank: Contributor
timestamp: October 17, 2019, 03:59:37 am
content: Web Archive has a copyhttps://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.htmlHe has a mirror here.http://zx80.netai.net/grant/index.htmlhttp://searle.wales/twitter for updates and links to the mirrorhttps://twitter.com/zx80nut?lang=en

author: CJay
author_rank: Super Contributor
timestamp: October 17, 2019, 05:22:24 am
content: Quote from: nockieboy on October 16, 2019, 01:42:20 pmBugger.Wish I'd archived it all now.

author: hamster_nz
author_rank: Super Contributor
timestamp: October 17, 2019, 06:21:39 am
content: Quote from: jhpadjustable on October 16, 2019, 11:35:23 pmDVI-D is a direct replacement of the VGA signals with streams of bits. It is from the FPGA designers point of view just a little bit bolted onto the end of the video pipeline, rather than the DACs.The only trick (if you can call it that) I'd the high speed digital signals from the FPGA to the connector, but for standard 640x480 that isn't too exacting, and you can get away with quite a few sins. The raw bit rate is 250Mb/s per channel, so bits are around meter long on the wire (ignoring velocity factors and so on), and the protocol is designed to resist errors.A few mm of length mismatch or an impedance bump is far less a problem then at 1080p rates.

author: nockieboy
author_rank: Super Contributor
timestamp: October 17, 2019, 01:03:29 pm
content: Quote from: CJay on October 17, 2019, 05:22:24 amDon't panic CJay - Codex has linked to some excellent mirrors and I can personally vouch for the z80.netai.net one, it's all there.Quote from: Codex on October 17, 2019, 03:59:37 am

author: nockieboy
author_rank: Super Contributor
timestamp: October 17, 2019, 01:32:29 pm
content: Quote from: dferyance on October 16, 2019, 05:43:02 pmA resistor ladder is the simplest way to get a colour output I guess, but it seems a little... inexact... and dependant on resistor tolerances and chosen values, so when I saw an example using a video DAC I thought I'd likely want to give that a try.I'm not sure I understand colour encoding/generation properly, so would appreciate correction if I'm wrong, but whilst thinking about the frame buffer design the other day I gave some thought to how the data would be stored in the frame buffer. Storing discrete values for R, G and B channels using a bit (or bits) seems a little wasteful. If I want 64 colours for example, I could use 2 bits per channel for 6 bits of RGB per pixel, or one byte per pixel (with a couple of bits spare) in the frame buffer. Thing is, if I want to go to 3 bits per channel or more, I'm looking at two bytes per pixel and doubling the memory requirement for a single frame.So I hit on the idea of using a look-up table for the colours. Is that the 'palette system' you're referring to? Basically, I'd have one byte per pixel in the frame buffer. Each byte would be a value between 0 and 255, so when the 'pixel' is read from the frame buffer, the value would be used to look up the RGB value in the LUT, which could be anything up to 24-bit values that would get passed out to the DAC...... would that work? The other thing is, I don't really know anything about FPGAs - I get the impression they're fast, so using a LUT for the RGB values shouldn't slow the FPGA down so much that it couldn't keep up with the clock?The FPGA I have currently isn't up to what I want from it, really - it's an Altera Cyclone II EP2C5T144, so doesn't have the RAM I need for a frame buffer for anything more than straight text display. I'm wondering if using an external SRAM chip would be the way to go for the frame buffer? Would something with an access time <15ns for example be fast enough? Alternatively, I'm waiting on a Xilinx Spartan 6 which I'll likely develop on instead. That has a 32MB SDRAM on its board, I might experiment using that for the frame buffer if the RAM in the Spartan isn't enough (though I think I can make the internal RAM dual-port, which is highly desirable for a frame buffer?)Quote from: dferyance on October 16, 2019, 05:43:02 pmI'm intending to interface the VGA controller with my Z80-based computer running at 8 MHz. I'm not hung-up on direct frame-buffer access for the Z80 at all - in fact, I'd rather not mess with the Z80's memory space at all if another interface method is fast enough. Unless anyone here tells me otherwise, I'm going the route of having the Z80 send commands to the FPGA, which it will interpret and modify the frame buffer's contents accordingly. How the Z80 does that, I haven't decided yet, but I could use a serial connection from the Z80's SIO, I could use my Z80's hardware I2C port, or a more direct connection using OUT commands and the data bus, which I'm erring towards as I feel it will be the quickest of the three. An SPI interface isn't currently an option, but may be later if I ever finish a hardware SPI interface for my system.

author: dferyance
author_rank: Regular Contributor
timestamp: October 17, 2019, 01:40:32 pm
content: QuoteYes, that is exactly right. The palette is a LUT. A 256 byte LUT can pretty easily fit in a FPGA so the lookup can be quite fast. One common technique used for old DOS VGA games is to modify the palette to do simple animations. This is called palette shifting. So while the palette can be limiting as you can only have 256 colors at a time it can also be handy as well.

author: nockieboy
author_rank: Super Contributor
timestamp: October 17, 2019, 01:52:55 pm
content: Quote from: NorthGuy on October 16, 2019, 08:10:33 pmErr, well a couple of reasons really - I'm not very knowledgeable when it comes to electronics (experienced users of the forum who remember my DIY Z80 computer posts will agree!), and because of that I guess the other reason is that I didn't even know it would be an option!I guess the concept of VGA is relatively easy for me to grasp, but if I can do HDMI then I most certainly will!Quote from: kizmit99 on October 16, 2019, 09:14:56 pmThanks kizmit - that second link is certainly intriguing and has piqued my interest.

author: nockieboy
author_rank: Super Contributor
timestamp: October 17, 2019, 01:59:57 pm
content: Quote from: dferyance on October 17, 2019, 01:40:32 pmMy goal is to build a computer as good as, if not better than the first computer I ever had (an Amstrad CPC464 back in the 80's). The only challenge left for me to meet or exceed is the graphics display, so 256 colours at a time may be 'limiting', but it'll blow my old Amstrad out of the water (it had a 27 colour palette)!My ignorance of FPGAs is limiting my understanding here, though. How could the palette be modified 'on the fly' in an FPGA? Oh, unless it's stored in block RAM I suppose?

author: Berni
author_rank: Super Contributor
timestamp: October 17, 2019, 02:40:49 pm
content: The thing is that R2R DACs built out of just cheap standard tolerance resistors are only really good enough to get you about 4 bits of resolution reliably. Past that the resistor tolerances start becoming a significant enough part of the signal that the non linearity of the steps messes up the least significant bits. So its not really worth it building a 8bit R2R ladder DAC as its performance won't be all that great.If you want proper 24bit color you are better off buying a proper DAC chip that gives you 8bits per channel. This can be a purpose built VGA DAC or just 3 separate generic 8bit DACs for each color. By the time you have all of this you will essentially have a 24bit RGB bus(Also called DPI bus) feeding it and this is a simple standard video bus and this means you can replace your 24bit VGA DAC chip with a LCD panel and it will work, or you can replace it with a RGB to LVDS or RGB to HDMI converter to drive larger serial LCD panels or display it on a modern TV. Tho this conversion can also be done inside a FPGA, but does tend to need specialized serdes capability to go fast enough for larger resolutions.And once you have 24bit color you can do palatalized 256 colors nicely because each pallet entry can pick from the 16 Milion available colors that you are now capable of displaying. Color palettes are just a way of keeping the amount of data down inside the graphics subsystem, its not a way of getting around the limitations of the video output hardware as it still has to be capable of reproducing all the colors the palette would want to ask for, its just a workaround that the graphics hardware is not powerful enough to tell the video output hardware exactly what color it wants, so its job is made easier by having to only pick from 256 colors.

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 17, 2019, 02:56:25 pm
content: Quote from: nockieboy on October 16, 2019, 01:42:20 pmIdeally, you could consider using a dedicated framebuffer (dedicated RAM chip) for the display.The CPU could for instance access it (to write to it or read from it) via some kind of memory mapping scheme, like maybe in chunks ("windows") of 8KB, and a bank selection mechanism. More efficient than using I/O accesses IIRC. Of course, when the CPU would access the framebuffer, it could only do so when it's not being read by the display controller, but when the CPU is not accessing the framebuffer, it could mind its own business with its own RAM without any penalty.

author: nockieboy
author_rank: Super Contributor
timestamp: October 17, 2019, 03:14:03 pm
content: Quote from: SiliconWizard on October 17, 2019, 02:56:25 pmI had considered this before - my system's MMU breaks the memory down into 16KB banks with a total of 4 MB of physical memory space. I could just break out one (or more) of the eight 512 KB chip sockets to dedicate them to being a frame buffer, I suppose. The only issue is that I'd need to put together some switching logic to isolate their data and address bus from the Z80's whilst the Z80 isn't accessing the frame buffer, and some way of making the Z80 wait until the frame buffer is free before access is allowed to it (I guess I could read an IO port on the FPGA which would go low when the display is in a front porch, for example.)I guess whether I'd want to go that route, with the additional complexity of creating the 'shared RAM' interface and control logic, would depend on how much mileage I can get out of using an on-board frame buffer on the Spartan 6, or whether just sending commands and data one OUT at a time would be too much of a bottleneck.EDIT:Ah, answered my question with a quick Google - the Spartan 6 has up to 18 KB of RAM on board. Subtract 2 KB for symbol/character set storage (unless ROM is a separate entity to the RAM?) and I'm struggling to do much with it on a resolution larger than 160x120. Looks like the frame buffer will have to go into the SDRAM and I'll need a way to buffer commands/data from the Z80 whilst the controller waits for a 'porch window' to do what it needs to do with the frame buffer.

author: legacy
author_rank: Super Contributor
timestamp: October 17, 2019, 03:37:49 pm
content: Shared ram chips, in DIP-package, are about 2 Kbyte.The alternative is to force the Z80 releasing the bus.

author: CJay
author_rank: Super Contributor
timestamp: October 17, 2019, 03:39:37 pm
content: Quote from: nockieboy on October 17, 2019, 01:03:29 pmYeah, found them and they're safe now

author: SiliconWizard
author_rank: Super Contributor
timestamp: October 17, 2019, 04:24:43 pm
content: You could also design your MMU so that CPU and video accesses are interleaved. I dunno how fast your CPU is going to run, but if it's a few MHz (as that was back in the day) that should pose no issues.Any Spartan 6 certainly has more than 18KBytes of embedded RAM. The LX4 (smallest) has 216Kbits (27KBytes), and the LX45, which is still reasonable price-wise, has 2088Kbits (261KBytes!)You confused the "18Kb" (Kbits) figure for the Spartan 6, which is the individual size of the RAM blocks, certainly not the total available!

author: mariush
author_rank: Super Contributor
timestamp: October 17, 2019, 08:42:20 pm
content: Any reason you can't use a microcontroller to generate the VGA signal?There's cheap microcontrollers (under 10$) which exceed 200 Mhz and fast DACs are cheap, if you don't want to use resistors.

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: October 17, 2019, 11:49:55 pm
content: Quote from: SiliconWizard on October 17, 2019, 04:24:43 pmYep, just like almost all the home computers of the 1980s. But that requires some close coupling between the video hardware and the rest of the system, which he said he wanted to try to avoid. With the huge difference in memory bandwidth demand between the CPU and 640*480*8bpp, I can understand that.Personally I'd have put a Z80 soft core and an SDRAM controller on the FPGA and called it 80% doneQuote from: mariush on October 17, 2019, 08:42:20 pmAny reason you wouldwantto bit bang video, other than toshow off for the demoscene?