Author Topic: FPGA VGA Controller for 8-bit computer  (Read 510669 times)

0 Members and 4 Guests are viewing this topic.

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2812
  • Country: nz
Re: FPGA VGA Controller for 8-bit computer
« Reply #150 on: October 29, 2019, 04:26:31 am »
If the OP is making his own board, or is expecting to, he can always change the crystal oscillator from 25Mhz to 27Mhz.
Or just add a second (third, fourth, you get the point) oscillator on a board. This is an advantage of making your own board - you can place whatever stuff you need (or you think you need :) ).
Just make sure it is connected to a clock-capable pin.   |O

Planning for high speed transceiver reference clocks is the biggest pain. It pays to build a shell of a design just to prove that your desired clocking structure and channel bonding will work.
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2839
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #151 on: October 29, 2019, 05:02:01 am »
Just make sure it is connected to a clock-capable pin.   |O
This is the mistake I made on my very first FPGA board :-DD And never again after that 8)

Planning for high speed transceiver reference clocks is the biggest pain. It pays to build a shell of a design just to prove that your desired clocking structure and channel bonding will work.
If you mean MGTs, it's actually quite easy as there are only so many ways to do it. Things get a bit "interesting" with Kintex because their transceivers are arranged in a column, as opposed to top and bottom sides of a die which have dedicated routes between each other. On Kintex you can only route clock one quad above or below the one which have clock source connected to. This is why it's impossible to implement PCIE x16 on Kintex devices - only 12 MGTs can be reached by a single clock. At least it's possible to implement a PCIE 3.0 x8 interface (with a bit of a soft logic as hardIP only supports PCIE 2.x speed).

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #152 on: October 29, 2019, 09:46:57 am »
$15.86 for 1, $13.94 each for 25, $13.36 each for 100.

With only 1 small BGA chip (14mm X 14mm), and you using the outer pads only, you can make this work on a 4 layer board and with tinned pads, and because the IC is so small, you can get away with only a good quality hot air gun and a syringe of flux, no oven needed.  Watch a few of Louis Rossman repairs of mac-books where he re-solders small BGA chips.  As long as you have a PCB with solder mask, you can do it easily this way.  (Now, I don't mean populate your PCB with small BGA ICs all over the place.  Dealing with 1 small IC on each PCB will be easy enough with a healthy tube of flux and a hot air gun will be manageable unless you are building 100s of them.  Then use a solder paste stencil and toaster oven...)

Wow, okay, sounds like I need to do some research into this then! Thanks BrianHG!  :-+


As for the crux of your system, I'll make a reply tonight and you'll laugh as 33% of your problems vanish with around 2 paragraphs of words...

Sounds great!  :popcorn:

There's a bit of confusion in the thread on DVI-D vs. HDMI. DVI-D is a digital video standard, and basically open and well-documented. HDMI is a superset of DVI-D that includes in-band packets to set color spaces, send audio data, communicate remote control data, defend Hollywood against their customers, etc. and basically proprietary and NDA-infested.

DVI-D transmitters won't generate the packets you need for audio, and HDMI transmitter public data sheets are intentionally incomplete. To my mind, that means you would need to build (or borrow) a transmitter on board the FPGA so that you can generate those packets, glean data about the register configuration for an HDMI transmitter chip from public leaks such as Linux kernel drivers, OR give up on HDMI audio and settle for an analog or S/PDIF output.

Haha! Fair enough, so it's not HDMI I'm going for but DVI-D. Looks like I'll have to handle sound through an analogue or S/PDIF output then.

On that note I would strongly caution that you not make any more design or feature decisions until you have hands-on experience with the medium in which you are working. Even then I would wait until I have first picture coming out of the board to decide how to get from spec to implementation. There are subtleties that you might not be considering, such as that block RAMs are still just dozens of individual separate blocks spread over the chip and you (or the synthesis tool) have to use logic and routing to aggregate them, which can get very expensive (in the sense of latency and  logic resources consumed) for a large array.

I'm keen to get started on the practical aspects of the project, but at the moment work and home life are preventing me from having any major blocks of time where I can make a start, so in the meantime I like to glean as many pearls of wisdom from you guys here as possible.  I've got an Altera Cyclone II EP2C5T144 board, I guess I can make a start on that?  The code should transfer to a Spartan 6, or MAX 10 or Lattice chip without major issues at this stage as the code will be VERY basic, and future FPGAs that I transfer the code to will have more resources rather than less.

If you have a 25MHz source, you multiply it by 54 to get a VCO frequency of 1350Mhz, which is in the allowable range of 800MHz to 1600Mhz.

- Divide the VCO by 50 to get 27MHz for your pixel clock
- Divide the VCO by 10 to get your clock to drive the serializers the for DVI-D outputs (using DDR mode).

Marvellous, thanks hamster_nz.  This is only an issue whilst I'm developing the design on an eval/dev board as the clock source is fixed (to 25MHz usually).  When I make my own custom board, I'll use a 27MHz clock source.

Oh, it seems that the HDMI spec owners are sending out takedown notices: https://glenwing.github.io/docs/HDMI-1.4b.pdf

Might pay to look for "hdmi specification 1.4 filetype:pdf" in everybody's favorite web search engine while you can, just for future reference.

Well spotted - thanks for that.  I've got a copy of the specs now.  :-+

If the OP is making his own board, or is expecting to, he can always change the crystal oscillator from 25Mhz to 27Mhz.

Of course - and that's my plan, but before I get to the stage of making my own board, I'll be using an eval/dev board which has the 25MHz clock source. Probably. :)

EDIT:

Thinking back to BrianHG's comments about using the outer pins of the Lattice chip, I thought it might be a good idea to work out how many IO pins I'm going to need..

System side:
  • 21x address bus
  • 8x data bus
  • 10x command signals (maybe cut down to 7, depends on design)

Video side:
  • 26x VSYNC/HSYNC/RGB output (much less if the FPGA is going to produce the DVI-D stream itself)
  • 4?x audio output

GPU utility:
  • 5x USB Blaster programmer connection?
  • 6x Boot prom connection?
  • ??x DRAM connection, maybe?

That's an bare minimum of 80 I/O pins, not including external GPU memory connections and clock sources for the FPGA.  Is that about right?
« Last Edit: October 29, 2019, 10:02:24 am by nockieboy »
 

Offline jhpadjustable

  • Frequent Contributor
  • **
  • Posts: 295
  • Country: us
  • Salt 'n' pepper beard
Re: FPGA VGA Controller for 8-bit computer
« Reply #153 on: October 29, 2019, 11:59:31 pm »
Haha! Fair enough, so it's not HDMI I'm going for but DVI-D. Looks like I'll have to handle sound through an analogue or S/PDIF output then.
For now. If you transmit TMDS directly from the FPGA rather than use an external TMDS transmitter, you leave your audio options open.

Quote
I'm keen to get started on the practical aspects of the project, but at the moment work and home life are preventing me from having any major blocks of time where I can make a start, so in the meantime I like to glean as many pearls of wisdom from you guys here as possible.  I've got an Altera Cyclone II EP2C5T144 board, I guess I can make a start on that?  The code should transfer to a Spartan 6, or MAX 10 or Lattice chip without major issues at this stage as the code will be VERY basic, and future FPGAs that I transfer the code to will have more resources rather than less.
Ah, but what have you done with the Cyclone 2 board so far? You don't need a very great block of time to get a blinky up. :) You don't need more than a few not-very-great blocks of time to get the system bus-side interface up, maybe map a block RAM or two onto the bus. These are things you can work on without any external RAM or video connections.

System side: looks alright. If you monitor the Z80's multiplexed bus directly, maybe you could narrow the address bus requirement by 8 pins or more. You could also replace a few address lines if you let the memory board do your decoding and run a lead from the unused socket's !CS to the GPU, or mirror the same decoding function on the GPU board. It might go against the spirit of maximum integration, but when you're pin-limited a touch of off-chip logic is sometimes the best approach.

It would be much better if we knew exactly how you were getting a 22-bit address space out of a 16-bit CPU address space. I'm going to wildly guess: you're using an 8-bit writable latch, with its own memory addressing, to choose a 16k block of the 4MB RAM/ROM space to map into a preset 16k of the Z80's address space, with peripherals and/or a BIOS-like ROM fixed-mapped into the rest of the Z80 address space. Would you be better off allocating another 16k or so of the flat Z80 address space to implement an independent bank switching scheme inside the GPU?

Video-audio: 3 is enough for audio output. One clock, one data, one word-select. One pin if you decide to do S/PDIF transmission on the chip.

If using an external transmitter, you also need a pixel clock output. You also might gain from cutting back on the bits per channel. Choose some photos, process them with a posterize filter, and see how few bits you can tolerate. RGB565 is the compromise I'd choose: photos still look very good, fits neatly into 16 bits, not too anachronistic. If you find the slight greening of some greys objectionable, maybe you can drop one of the green bits. The unused LSBs can be tied high or low.

GPU utility: JTAG and boot PROM pins are usually dedicated and not movable. In the final version you will only need one or the other. If using a four-layer board you might be able to escape-route them between power planes on the power layer since they're relatively non-critical. A serial configuration memory is usually a 25 series SPI flash so you only need four signals. Depending on the FPGA chosen, you may need pullups or straps to configuration pins to choose the configuration source. You may be able to treat some or all of the config pins as supply pins, which could keep the layout process (and the layout artist) that much saner.

DRAM: Figure 11 or 12 pins for DRAM addressing, 4, 8, or 16 pins for data, 4-6 for control, and 0-4 for clocking, depending on the particular DRAM technology you use.
« Last Edit: October 30, 2019, 01:44:18 am by jhpadjustable »
"There are more things in heaven and earth, Arduino, than are dreamt of in your philosophy."
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #154 on: October 30, 2019, 03:48:48 am »

Video side:
  • 26x VSYNC/HSYNC/RGB output (much less if the FPGA is going to produce the DVI-D stream itself)
  • 4?x audio output

Only use 12 or 16 IO for RGB, 15 bit color, you will need a ENABLE out if you will be using the TI TFP410 for DVI.  it accepts multiplexed data meaning you can feed 24 bit color on 12 outputs.  To transmit HDMI direct, you need 8 outputs (4 balanced pairs) plus another 5 IOs for the DDC and hot plug detect features.

-----------------------------------------------------------------------------------------------------------------------------------------------

If you have a 'Cyclone II EP2C5T144', today, you should already have your master sync generator and VGA output generating a frame where you can make a dummy test pattern.

It already has enough internal ram for you to replicate an Atari 400 video generator with all it's graphics capabilities, however, due to simplicity, I would at least make a text mode generator.

Begin by making you raster generator with programmable window margins and a 2 color monochrome text mode.

Here is my first bit of help:
#1 make a sync generator which can make a programmable raster, programmable HS, Programmable VS, + Horizontal enable and vertical enable + the 2 combined for you active video region enable.

#2 I've attached a small character generator I one made.  It uses 20kbit.  Has an Atari 800 font with display ram.  The output is an enable signal for superimposing the image on an existing background plus a 3 bit color image (2 bit for font and 1 bit for higher colors, you may shrink the design to a 1 bit font with a little effort saving you ram bits).  I have not included the external palette.v and video mixer.v as they are 30bit color examples for a larger chip.  Also, I have not included my programable sync generator as I need to re-install quartus to verify I'm giving you the right files.
(I only work in Verilog)

Start with your 640x480, or 720x480 raster generator and look at my osd routine and within quartus, you should be able to generate a symbol file for my osd.....v which you can paste into your block diagram.  Until you wish to write to the text display memory, you can GND those signals.  The included memory initialization files have the OSD Font and a test text dump for the display memory.
« Last Edit: October 30, 2019, 04:16:46 am by BrianHG »
 

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5031
  • Country: si
Re: FPGA VGA Controller for 8-bit computer
« Reply #155 on: October 30, 2019, 06:49:58 am »


I'm keen to get started on the practical aspects of the project, but at the moment work and home life are preventing me from having any major blocks of time where I can make a start, so in the meantime I like to glean as many pearls of wisdom from you guys here as possible.  I've got an Altera Cyclone II EP2C5T144 board, I guess I can make a start on that?  The code should transfer to a Spartan 6, or MAX 10 or Lattice chip without major issues at this stage as the code will be VERY basic, and future FPGAs that I transfer the code to will have more resources rather than less.

Yes that Cyclone II board is definitely a good place to start if you already have it.

Just bodge wire together a R2R DAC to one of those IO headers and connect it to a SubD 15 connector so that you can plug it into VGA. Believe me you will learn a lot by the time you have a picture on your monitor.

Once you have that you can also bodge wire your Z80 memory bus onto more pins so that you can actually draw on the screen in software, then just build up from there. You will have a much easier time designing the rest of your system once you see what the strong and weak points of FPGAs are.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #156 on: October 30, 2019, 11:41:45 am »
Ah, but what have you done with the Cyclone 2 board so far? You don't need a very great block of time to get a blinky up. :)

Funny you should mention that - after mentioning that I'd got a Cyclone 2 board yesterday, I thought I should actually get the thing out of its packaging and try using it!  I got a blinky up and running last night.  Was a worthwhile exercise, too - there were a couple of hurdles to overcome with silly things like installing the right USB drivers for the Blaster and working out fiddly stuff like how to use the pin manager software, but once that was done I progressed from a single blinking light to a 3-bit counter display in a minute or two (the board only has 3 LEDs).

Going to start working through the fpga4fun tutorials over the next couple of days.  :-+

You don't need more than a few not-very-great blocks of time to get the system bus-side interface up, maybe map a block RAM or two onto the bus. These are things you can work on without any external RAM or video connections.

You could also replace a few address lines if you let the memory board do your decoding and run a lead from the unused socket's !CS to the GPU, or mirror the same decoding function on the GPU board. It might go against the spirit of maximum integration, but when you're pin-limited a touch of off-chip logic is sometimes the best approach.

Absolutely.  As part of my mantra of starting small and building up from there, this is where I'll start out - and funnily enough, I was looking at the memory board on my Microcom earlier this morning, daydreaming whilst the PC booted up (as you do), and looking at the empty memory chip socket and the thought occurred that I could run all the connections I'd need for the initial FPGA designs straight from the empty memory socket - that'd cut the system-side IO pins down to 30 at most as I'd only need A0-A18 for the 512KB window.

It would be much better if we knew exactly how you were getting a 22-bit address space out of a 16-bit CPU address space. I'm going to wildly guess: you're using an 8-bit writable latch, with its own memory addressing, to choose a 16k block of the 4MB RAM/ROM space to map into a preset 16k of the Z80's address space, with peripherals and/or a BIOS-like ROM fixed-mapped into the rest of the Z80 address space.

Almost. :-+ My MMU addresses up to 4 MB of memory by intercepting A14 & A15 from the Z80, replacing them with EA14 & EA15 and a further 6 address lines, EA16-EA21, using two 74HCT670 4x4 register files, which means I can map ANY 16 KB physical memory bank into any of the four 16KB areas in the Z80's logical 64 KB memory space.  The bootstrap ROM has to be in the topmost chip socket (due to pull-ups on the EA address lines as the system's initial power-on state is with the MMU off), so at power-on the topmost 16KB bank of physical memory is copied across the entire 64 KB logical memory space.  That's more than enough for the Z80 to execute some bootstrap code, which maps some RAM banks into the logical memory space for the bootstrap to make use of, then turns the MMU on.

My memory cards have four 'sockets' on them for chips that are selected by EA19 & EA20 (well, three as the first one is an SMD SRAM chip as RAM is sort of compulsory in most computer systems).  The other three are DIP sockets.  Each socket can take up to 512 KB chips, so one memory card gives a potential of 2 MB memory space.  I can add an identical memory card to the system which adds another 4 'sockets' and pull a jumper, which allows EA21 to select the memory card, giving 4 MB memory space.

Would you be better off allocating another 16k or so of the flat Z80 address space to implement an independent bank switching scheme inside the GPU?

Don't think so - I can allocate anything up to 512KB to the GPU - unless I add DRAM or SRAM as external memory for the GPU, I can't see me needing all that space to access the GPU's internal video RAM...?

If you have a 'Cyclone II EP2C5T144', today, you should already have your master sync generator and VGA output generating a frame where you can make a dummy test pattern.

It already has enough internal ram for you to replicate an Atari 400 video generator with all it's graphics capabilities, however, due to simplicity, I would at least make a text mode generator.

Grant Searle has an entire Z80/6809 computer AND VGA output that fits into one of these devices.  I was toying with the idea of taking his code and stripping everything but the VGA generation parts out and tweaking it to take external input via a serial interface initially, so that I can play with the generation of characters etc. and get a working video output for my Microcom very quickly that I can then build upon, as Grant's code implements VT-100 emulation, it should be quite flexible and may be a good base to learn from?

Begin by making you raster generator with programmable window margins and a 2 color monochrome text mode.

Here is my first bit of help:
#1 make a sync generator which can make a programmable raster, programmable HS, Programmable VS, + Horizontal enable and vertical enable + the 2 combined for you active video region enable.

This is key to having various screen modes and is certainly on my to-do list!  :-+

#2 I've attached a small character generator I one made.

You have? I can't find it? :-//

It uses 20kbit.  Has an Atari 800 font with display ram.  The output is an enable signal for superimposing the image on an existing background plus a 3 bit color image (2 bit for font and 1 bit for higher colors, you may shrink the design to a 1 bit font with a little effort saving you ram bits).  I have not included the external palette.v and video mixer.v as they are 30bit color examples for a larger chip.  Also, I have not included my programable sync generator as I need to re-install quartus to verify I'm giving you the right files.
(I only work in Verilog)

Thank you very much for your help.  I'm very much a visual learner and having an example I can see working helps my understanding massively.  I'm not precious over Verilog/VHDL to be honest, will likely go with whichever seems most logical to me.

Start with your 640x480, or 720x480 raster generator and look at my osd routine and within quartus, you should be able to generate a symbol file for my osd.....v which you can paste into your block diagram.  Until you wish to write to the text display memory, you can GND those signals.  The included memory initialization files have the OSD Font and a test text dump for the display memory.

Thanks again - it's immensely valuable just seeing how these projects fit together at the moment, so anything like this is a great help.  :phew:

Just bodge wire together a R2R DAC to one of those IO headers and connect it to a SubD 15 connector so that you can plug it into VGA. Believe me you will learn a lot by the time you have a picture on your monitor.

Once you have that you can also bodge wire your Z80 memory bus onto more pins so that you can actually draw on the screen in software, then just build up from there. You will have a much easier time designing the rest of your system once you see what the strong and weak points of FPGAs are.

There are weak points to FPGAs?  :o ;)

Well, that's the plan.  I'm hoping I can make some progress over the next few days - will post some pics if I can.  ;D
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #157 on: October 30, 2019, 12:13:18 pm »

If you have a 'Cyclone II EP2C5T144', today, you should already have your master sync generator and VGA output generating a frame where you can make a dummy test pattern.

It already has enough internal ram for you to replicate an Atari 400 video generator with all it's graphics capabilities, however, due to simplicity, I would at least make a text mode generator.

Grant Searle has an entire Z80/6809 computer AND VGA output that fits into one of these devices.  I was toying with the idea of taking his code and stripping everything but the VGA generation parts out and tweaking it to take external input via a serial interface initially, so that I can play with the generation of characters etc. and get a working video output for my Microcom very quickly that I can then build upon, as Grant's code implements VT-100 emulation, it should be quite flexible and may be a good base to learn from?

Begin by making you raster generator with programmable window margins and a 2 color monochrome text mode.

Here is my first bit of help:
#1 make a sync generator which can make a programmable raster, programmable HS, Programmable VS, + Horizontal enable and vertical enable + the 2 combined for you active video region enable.

This is key to having various screen modes and is certainly on my to-do list!  :-+

#2 I've attached a small character generator I one made.

You have? I can't find it? :-//
Just click on the link at the bottom of my post, it says " * Altera_OSD_20kbit.zip (12.86 kB - downloaded 0 times.) "
Quote
It uses 20kbit.  Has an Atari 800 font with display ram.  The output is an enable signal for superimposing the image on an existing background plus a 3 bit color image (2 bit for font and 1 bit for higher colors, you may shrink the design to a 1 bit font with a little effort saving you ram bits).  I have not included the external palette.v and video mixer.v as they are 30bit color examples for a larger chip.  Also, I have not included my programable sync generator as I need to re-install quartus to verify I'm giving you the right files.
(I only work in Verilog)

Thank you very much for your help.  I'm very much a visual learner and having an example I can see working helps my understanding massively.  I'm not precious over Verilog/VHDL to be honest, will likely go with whichever seems most logical to me.

Start with your 640x480, or 720x480 raster generator and look at my osd routine and within quartus, you should be able to generate a symbol file for my osd.....v which you can paste into your block diagram.  Until you wish to write to the text display memory, you can GND those signals.  The included memory initialization files have the OSD Font and a test text dump for the display memory.

Thanks again - it's immensely valuable just seeing how these projects fit together at the moment, so anything like this is a great help.  :phew:

Stick with 1 video mode of 720x480.  Your different video modes will just be different pixel multiples sitting on top of that master reference mode.

Also, write your own VGA raster generator in Verilog from scratch.  You will need the learning experience and there will be special additions you will need to make for you 8bit bitplane video modes and things like sprites in the future which will be nothing but headaches if you are trying to dissect someone else coding style while sticking/adding your own stuff  on top.

A VGA generator is so simple that you should be posting you code if you have problems here on this forum asking for help and recommendations.

The OSD generator I gave you illustrates a simple level of using Altera's dual port memories & the effort I went through to deal with the fact that to get the top clock or FMAX capabilities, you need to clock latch the address going into the ram as well as clock the data coming out making a 2 clock delay from address to valid data. You will see I have additional delay latches along the video pipe to synchronize the control signals coming in to a new set of output delayed controls which are parallel with the font generated image.

The OSD generator I made is just to give you a boost and play.  You will be remaking your own eventually using 1 huge block of memory where you can selectively choose the base memory for the font as well as where each line of the display output points to in the same huge chunk of memory.

--------------------
Note in my osg_generator.v code, the HS it takes in needs to be only 1 pixel wide, and the generator will start spitting out pixels within 5 clocks.  This means that within your VGA sync generator, you need to have a dedicated horizontal pulse output just for the OSD generator.  This pulse should be in the middle of the active video display window, not at the beginning of the actual horizontal sync. Same goes for the VS signal on my OSD generator input.  It should pulse for 1 line of video prior to the beginning of the line you want your display output.  I recommend you make these 2 horizontal and vertical pulse position programmable so you can move my test box around the screen with just the beginning 2 coordinates.
As you add sprites, other video modes and potential programmable vertical interrupts, these will just be additional dedicated programmable X and Y coordinates which will be nothing more than and equality compare of your VGA sync generator's horizontal and vertical counters to a set of registers which your CPU can address and write new figures into.

I assume you are designing you own video generator and not trying to perfectly replicate an old EGA video card, correct?
« Last Edit: October 30, 2019, 12:42:52 pm by BrianHG »
 
The following users thanked this post: nockieboy

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5031
  • Country: si
Re: FPGA VGA Controller for 8-bit computer
« Reply #158 on: October 30, 2019, 12:41:57 pm »
There are weak points to FPGAs?  :o ;)

Well, that's the plan.  I'm hoping I can make some progress over the next few days - will post some pics if I can.  ;D

That they are expensive, complicated things that are a pain in the ass to program for.

But in exchange for that they can do some digital jobs that no other kind of chip out there can do. That's why FPGAs are only used in cases where the thing cant be done using a MCU or special digital chip. And your application of a custom video card certainly is something that only a FPGA can do.
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: FPGA VGA Controller for 8-bit computer
« Reply #159 on: October 30, 2019, 01:11:30 pm »
O.T.
does anyoneone happen to have doc regarding the timing of CGA frames?
it's for a crazy project, currently suspended, about interfacing a CGA-tube to a VDU on FPGA
VDU means "text only" display.
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #160 on: October 30, 2019, 01:24:23 pm »
O.T.
does anyoneone happen to have doc regarding the timing of CGA frames?
it's for a crazy project, currently suspended, about interfacing a CGA-tube to a VDU on FPGA
VDU means "text only" display.
I believe they match 240p RGB.  Same as 240p NTSC.
https://en.wikipedia.org/wiki/Color_Graphics_Adapter
Use a pixel clock of 14.31818Mhz and copy the line size, HS and VS timing of NTSC.
I think it's 910 horizontal and 262 lines vertical.  You would need to search NTSC's display window region and place you picture inside that...
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #161 on: October 30, 2019, 02:47:49 pm »
#2 I've attached a small character generator I one made.

You have? I can't find it? :-//
Just click on the link at the bottom of my post, it says " * Altera_OSD_20kbit.zip (12.86 kB - downloaded 0 times.) "

I must be going mad then, because I'm sure it wasn't there when I looked last time!  :-DD

Also, write your own VGA raster generator in Verilog from scratch.  You will need the learning experience and there will be special additions you will need to make for you 8bit bitplane video modes and things like sprites in the future which will be nothing but headaches if you are trying to dissect someone else coding style while sticking/adding your own stuff  on top.

Yes, fair point.  I've got some tutorials to work through first to learn the basics of VHDL/Verilog, but also doing this myself (mostly - will likely need some advice on the way!) will also be more of an achievement, too.  You can't beat knowing your code inside out.

The OSD generator I made is just to give you a boost and play.  You will be remaking your own eventually using 1 huge block of memory where you can selectively choose the base memory for the font as well as where each line of the display output points to in the same huge chunk of memory.

Thanks for the boost and all the help so far in this thread. I feel like I've got the spec for the goal I want to achieve, I just need to learn to play football now.  ;D

I assume you are designing you own video generator and not trying to perfectly replicate an old EGA video card, correct?

Definitely just designing my own video generator - I have no intentions of trying to replicate any other type of video card (unless it's a good design that would be foolish to ignore).
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: FPGA VGA Controller for 8-bit computer
« Reply #162 on: October 30, 2019, 06:39:18 pm »
@BrianHG
thanks!  :D
 

Offline jhpadjustable

  • Frequent Contributor
  • **
  • Posts: 295
  • Country: us
  • Salt 'n' pepper beard
Re: FPGA VGA Controller for 8-bit computer
« Reply #163 on: October 31, 2019, 10:11:56 am »
Almost. :-+ My MMU addresses up to 4 MB of memory by intercepting A14 & A15 from the Z80, replacing them with EA14 & EA15 and a further 6 address lines, EA16-EA21, using two 74HCT670 4x4 register files, which means I can map ANY 16 KB physical memory bank into any of the four 16KB areas in the Z80's logical 64 KB memory space.  The bootstrap ROM has to be in the topmost chip socket (due to pull-ups on the EA address lines as the system's initial power-on state is with the MMU off), so at power-on the topmost 16KB bank of physical memory is copied across the entire 64 KB logical memory space.  That's more than enough for the Z80 to execute some bootstrap code, which maps some RAM banks into the logical memory space for the bootstrap to make use of, then turns the MMU on.

My memory cards have four 'sockets' on them for chips that are selected by EA19 & EA20 (well, three as the first one is an SMD SRAM chip as RAM is sort of compulsory in most computer systems).  The other three are DIP sockets.  Each socket can take up to 512 KB chips, so one memory card gives a potential of 2 MB memory space.  I can add an identical memory card to the system which adds another 4 'sockets' and pull a jumper, which allows EA21 to select the memory card, giving 4 MB memory space.
Well done.  :clap:

512kB of video memory should be plenty.
"There are more things in heaven and earth, Arduino, than are dreamt of in your philosophy."
 
The following users thanked this post: nockieboy

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #164 on: October 31, 2019, 10:58:01 am »
Okay, some code...  Not sure how after all this talk of VHDL, but I've ended up writing this in Verilog!  :-DD

I've made a stab at writing the HSYNC and VSYNC counter, attached below.  Obviously, on its own it won't do anything but I'm working on the topmost component at the moment - I just want to check I'm going down the right lines and using the right timing values.  :)

EDIT:

Also, with all the tutorials and projects floating around on the internet, it's almost impossible to make this 100% my own work - which clearly this isn't - but at least I understand what I'm doing at the moment and am picking up the Verilog syntax.   ^-^
« Last Edit: October 31, 2019, 11:00:58 am by nockieboy »
 

Offline legacy

  • Super Contributor
  • ***
  • !
  • Posts: 4415
  • Country: ch
Re: FPGA VGA Controller for 8-bit computer
« Reply #165 on: October 31, 2019, 11:11:00 am »
Quote
For 60Hz VGA pix_clk should be 25.175MHz, but 25MHz should work?

Usually yes. VGA monitors are tollerant.
 
The following users thanked this post: nockieboy

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5031
  • Country: si
Re: FPGA VGA Controller for 8-bit computer
« Reply #166 on: October 31, 2019, 12:28:14 pm »
That verilog code looks pretty good for being your first time into it.

My only complaint is how reset is done. "if(reset)" should also have en else block under it so that it stops everything else from happening during reset. With these <= assignments only the last one  is executed, so high "pix_clk" signal would ignore reset. Also generally reset is also included in the sensitivity list on the always @ () to make it a asynchronous reset (This means reset works even when the clock is not running)

Also i would not give "pix_clk"  that name as it is not a clock. If you leave pix_clk high for more than 1 clock cycle you end up moving more than one pixel. So its behavior is more akin to a enable signal. I would call that something like pix_enable or pix_valid or pix_increment. Also the module name could be a bit more descriptive such as "sync_gen_640x480" or just call it "sync_generator" and turn the relevant "localparam" into "parameter". That way it will be 640x480 by default but upon instantiating the module you can add "#(320,240)" on the end and it will reconfigure it for that resolution without changing any code in this file. This is formally called a parameterized module.

In general old CRTs will take pretty much any timing you throw at it, be it weird porch times or a framerate of 98,777366 Hz it will display it all. Just as long as your timings are within reason for the CRTs cirucitry. So no things like frame rates of 5Hz or 1000Hz or having 10 or 10000 lines. Modern LCDs on the other hand will be quite picky on what you feed them as they have crappy upscalers that only know how to upscale certain resolutions properly and the LCD controller might get upset about unreasonably fast or slow timings a lot easier.
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2839
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #167 on: October 31, 2019, 01:23:19 pm »
Also generally reset is also included in the sensitivity list on the always @ () to make it a asynchronous reset (This means reset works even when the clock is not running)
It is a very bad idea to "generally" do that in FPGA designs because many internal blocks only have synchronous resets. I have seen many designs fail timing only because of these asynchronous resets!  Only do it when you absolutely need, and you know what you're going and are aware of consequences!
« Last Edit: October 31, 2019, 01:24:52 pm by asmi »
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #168 on: October 31, 2019, 01:27:00 pm »
That verilog code looks pretty good for being your first time into it.

Thanks Berni, but I can't claim all the credit - I've referred to a couple of different sources to put this code together.

My only complaint is how reset is done. "if(reset)" should also have en else block under it so that it stops everything else from happening during reset. With these <= assignments only the last one  is executed, so high "pix_clk" signal would ignore reset.

As okay, I understand.  I just intended reset to zero the counters, but I guess stopping everything from happening whilst reset is active will completely clear the display too for some feedback to the user.  reset is active low on the board, but I'm inverting it in the top-level module before it gets to the sync generator code here.

Also generally reset is also included in the sensitivity list on the always @ () to make it a asynchronous reset (This means reset works even when the clock is not running)

Thanks  :-+. It's tips like this I wouldn't otherwise pick up until something went wrong.

Also i would not give "pix_clk"  that name as it is not a clock. If you leave pix_clk high for more than 1 clock cycle you end up moving more than one pixel. So its behavior is more akin to a enable signal. I would call that something like pix_enable or pix_valid or pix_increment. Also the module name could be a bit more descriptive such as "sync_gen_640x480" or just call it "sync_generator" and turn the relevant "localparam" into "parameter". That way it will be 640x480 by default but upon instantiating the module you can add "#(320,240)" on the end and it will reconfigure it for that resolution without changing any code in this file. This is formally called a parameterized module.

All good points and the code is amended accordingly (updated file attached).

In general old CRTs will take pretty much any timing you throw at it, be it weird porch times or a framerate of 98,777366 Hz it will display it all. Just as long as your timings are within reason for the CRTs cirucitry. So no things like frame rates of 5Hz or 1000Hz or having 10 or 10000 lines. Modern LCDs on the other hand will be quite picky on what you feed them as they have crappy upscalers that only know how to upscale certain resolutions properly and the LCD controller might get upset about unreasonably fast or slow timings a lot easier.

Yeah, I'll be testing the FPGA out with an LCD screen so it waits to be seen how picky it is with the timings...  :-BROKE

I've also included the top-level module, vga01.v, for feedback.  Am using ASIC World as my Verilog reference.

Also generally reset is also included in the sensitivity list on the always @ () to make it a asynchronous reset (This means reset works even when the clock is not running)
It is a very bad idea to "generally" do that in FPGA designs because many internal blocks only have synchronous resets. I have seen many designs fail timing only because of these asynchronous resets!  Only do it when you absolutely need, and you know what you're going and are aware of consequences!

Aww jeez, Rick! Should I / shouldn't I?  :-//
 

Offline asmi

  • Super Contributor
  • ***
  • Posts: 2839
  • Country: ca
Re: FPGA VGA Controller for 8-bit computer
« Reply #169 on: October 31, 2019, 02:07:14 pm »
Aww jeez, Rick! Should I / shouldn't I?  :-//
Only use async reset if you need to. At least when working with Xilinx FPGAs. Mosts of their hard blocks (BRAM, DSP, SERDES) only have synchronous resets, so you will have to re-synchronize it internally anyways to reset these blocks. If my memory serves me, the only internal blocks that do have async reset are PLL/MCMM and flip-flops.

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5031
  • Country: si
Re: FPGA VGA Controller for 8-bit computer
« Reply #170 on: October 31, 2019, 03:05:32 pm »
That verilog code looks pretty good for being your first time into it.

Thanks Berni, but I can't claim all the credit - I've referred to a couple of different sources to put this code together.

My only complaint is how reset is done. "if(reset)" should also have en else block under it so that it stops everything else from happening during reset. With these <= assignments only the last one  is executed, so high "pix_clk" signal would ignore reset.

As okay, I understand.  I just intended reset to zero the counters, but I guess stopping everything from happening whilst reset is active will completely clear the display too for some feedback to the user.  reset is active low on the board, but I'm inverting it in the top-level module before it gets to the sync generator code here.

Copy paste is how most programming is done anyway. As long as you understand what the code does that you copy pasted you are fine. I think learning coding by example is the best way to go

And yes zeroing the counters looks like was your intention, but if the pix_clk is high the reset signal will have no effect if its 1 or 0 because the bottom part of the code will continue counting the registers. Its only when pix_clk is 0 that the reset will actually reset the counters. This is an important thing to know in Verilog since <= and = assignments work in different ways. Tho a reset is not really needed that much here since the counters could initialize in any random state and would eventually get back into its normal counting sequence once it gets to the end. Tho it tend to be good practice to start from a known reset state.

And yes a active high reset is usually used inside FPGAs, unlike the other way around on chips. There are architecture reasons for that and it makes more sense to just write "if(reset)"

Aww jeez, Rick! Should I / shouldn't I?  :-//
Only use async reset if you need to. At least when working with Xilinx FPGAs. Mosts of their hard blocks (BRAM, DSP, SERDES) only have synchronous resets, so you will have to re-synchronize it internally anyways to reset these blocks. If my memory serves me, the only internal blocks that do have async reset are PLL/MCMM and flip-flops.
Aww jeez, Rick! Should I / shouldn't I?  :-//
Only use async reset if you need to. At least when working with Xilinx FPGAs. Mosts of their hard blocks (BRAM, DSP, SERDES) only have synchronous resets, so you will have to re-synchronize it internally anyways to reset these blocks. If my memory serves me, the only internal blocks that do have async reset are PLL/MCMM and flip-flops.

Okay i admit i should have been a bit more clear about the reasons behind it.

This syncshornous vs synchronous reset is unfortunately quite chip architecture specific. Yes it is true that a lot of hardware blocks in FPGAs are synchronous reset only, but those are usually instantiated separately outside of always@ blocks and tend to have there reset signal directly connected to whatever your master system reset signal is. As such they don't tend to care what kind of reset it is, but it is strongly recommended that the edge coming out of reset is synchronized to the clock (Makes sure they all come out of reset on the same clock edge), so you will tend to have a reset synchronizer block all the way at the reset signal source to clean it up.

But where it does make a difference is to the logic inside the always@ statement as its behavior is directly affected by what signals are on the sensitivity list inside the (). Because different FPGAs have different LEs (Logic Elements) means that such logic might get implemented in a different way. I will admit i have only worked with Xilinx a few times so i can't say for sure whats best there. But for most of the lineup from Lattice and from Altera, including the Cyclone II they have LE blocks that include asynchronous clear signals. This means that a asynchronous clear has zero cost to the timing margin while a synchronous clear requires a extra AND gate in front. However this only works for clearing registers to zero with a active high reset signal, trying to set them to 1 with a active low reset signal would add extra logic that can slow things down.

But if you are not trying to push the design to high speeds it probably does not matter. But if you ignore the architecture i agree that synchronous resets are the safer way to go.
 

Offline nockieboyTopic starter

  • Super Contributor
  • ***
  • Posts: 1812
  • Country: england
Re: FPGA VGA Controller for 8-bit computer
« Reply #171 on: October 31, 2019, 08:31:18 pm »
Hmm.. I'm obviously missing something from the Quartus II manual, as I'm getting warnings when I try to compile the code I attached earlier.  I'm getting:

Code: [Select]
Warning (10230): Verilog HDL assignment warning at sync_generator.v(60): truncated value with size 32 to match size of target (10)
Warning (10230): Verilog HDL assignment warning at sync_generator.v(61): truncated value with size 32 to match size of target (10)
Warning (10230): Verilog HDL assignment warning at sync_generator.v(77): truncated value with size 32 to match size of target (10)
Warning (10230): Verilog HDL assignment warning at sync_generator.v(80): truncated value with size 32 to match size of target (10)

... which is referring to these lines:

Code: [Select]
60: assign x = (h_count < DA_STA) ? 0 : (h_count - DA_STA); // x is zero if current pixel is before display area
61: assign y = (v_count >= VA_END) ? (VA_END - 1) : (v_count); // y is VA_END-1 if v_count is outside display area

77: v_count <= v_count + 1;

80:   h_count <= h_count + 1;

It seems the warning is due to the literal values '0' and '1'?  Any way around that?

I'm getting similar warnings for unsigned ints in vga01.v as well.

Can't seem to bottom-out these warnings though:
Code: [Select]
Warning (10034): Output port "VGA_R[0]" at vga01.v(12) has no driver
Warning (10034): Output port "VGA_G[0]" at vga01.v(13) has no driver
Warning (10034): Output port "VGA_B[0]" at vga01.v(15) has no driver

I have assigned the signals to pins in the Pin Manager, but I'm clearly missing something else important as well?

Oh, and:

Code: [Select]
Warning (13024): Output pins are stuck at VCC or GND
Warning (13410): Pin "VGA_R[0]" is stuck at GND
Warning (13410): Pin "VGA_G[0]" is stuck at GND
Warning (13410): Pin "VGA_B[0]" is stuck at GND

I'm Googling for advice as well, but thought I'd pop these here in case anyone following along later comes up against the same problems.
« Last Edit: October 31, 2019, 08:35:56 pm by nockieboy »
 

Offline jhpadjustable

  • Frequent Contributor
  • **
  • Posts: 295
  • Country: us
  • Salt 'n' pepper beard
Re: FPGA VGA Controller for 8-bit computer
« Reply #172 on: October 31, 2019, 09:01:58 pm »
It seems the warning is due to the literal values '0' and '1'?  Any way around that?
By googling quartus warning 10230 I found Intel recommending explicit width specification on constants to suppress the warning.

Quote
I have assigned the signals to pins in the Pin Manager, but I'm clearly missing something else important as well?
I consider warnings in a synthesizer as polite FYIs. Unfortunately, that means I have to think when reviewing the warnings to see if they really are a problem, to see if something I really needed got simplified away.

The 10034 might be a real problem. Can we have a look at vga01.v? And your top file? Are you actually driving them? Do you need to drive them? The 13410 will probably not be a real problem of its own, if it resolves once you have provided drivers for that output port, and if you want them "stuck" at 0.

Another note, it helps readability to use the C conventions for the case of constants (all caps) vs. variables (not all caps).
"There are more things in heaven and earth, Arduino, than are dreamt of in your philosophy."
 

Online BrianHG

  • Super Contributor
  • ***
  • Posts: 8143
  • Country: ca
    • LinkedIn
Re: FPGA VGA Controller for 8-bit computer
« Reply #173 on: October 31, 2019, 09:42:41 pm »
Although:
Code: [Select]
// generate sync signals (active low for 640x480)
assign hsync = ~((h_count >= HS_STA) & (h_count < HS_END));
assign vsync = ~((v_count >= VS_STA) & (v_count < VS_END));
Is absolutely correct, however, the >= comparison and < do eat up gates when compiling and your output driving a pin will be a combination unlatched logic equation directly based on your output counter bits.  To get a clean output and better F-Max allowing Quartus's Fitter to better route the logic in your FPGA to meet timing constraints, I would:
A) Make Hsync and Vsync a register.
B) Inside your if (pix_enable), make the logic look like this

if (h_count == HS_STA) begin
    hsync <= 1;
 end else if (h_count == HS_END) hsync <= 0;
if (V_count == VS_STA) begin
    vsync <= 1;
 end else if (h_count == VS_END) vsync <= 0;

Remember, the == only uses 10 xor gates + a 10 input and gate since you are comparing 2 10 bit numbers.  With your GREATER than EQUALS and LESS Than, because of the fixed constants you chose, it may compile to a small number of gates with high efficiency maximum clock frequency (FMAX), but, once you change all your 'localparam's to registers which your CPU can address and change, including default 'reset' parameters, the >= and < will eat up gates and slow down your maximum possible FMAX.  (You may only be thinking about 25Mhz now, however, if you want your core to run at 200Mhz, with you pix_enable running once every 8 clocks, still a 25Mhz pixel, such an optimization will probably be needed further down the road, while just using the resources of your 8bit CPU to do the math when writing these new registers)

*Being registers, this now means that those outputs are delayed by 1 pixel clock, but, those outputs will be cleanly timed to the rising edge of your fpga PLL internal clock as those DFF register outputs don't have any logic gates to go through, those DFF register outputs will feed the IO pin directly.  (Though, I usually add another DFF stage/pipe to all my DAC and sync outputs allowing the compiler/fitter to bury the logic anywhere deep in the FPGA, the use each pins macrocell flipflops registers to drive the pin itself generating the cleanest possible outputs.)

As for your Assign X&Y, again, doing all that realtime arithmetic is not a problem:
Code: [Select]
// keep x and y bound within the display area
assign x = (h_count < DA_STA) ? 0 : (h_count - DA_STA); // x is zero if current pixel is before display area
assign y = (v_count >= VA_END) ? (VA_END - 1) : (v_count); // y is VA_END-1 if v_count is outside display area

However, like the HSync and Vsync, personally, I make these outputs a single bit which turns on or off using the simple equality == trick I used to generate the Hsync and Vsync.  I rely on my video graphics generator to have an address generator which may increment count every single, every second, or every third/fourth line.

Also, not just that one master image X&Y output enable which is REQUIRED by all DVI transmitters and which may also be used as an image crop mute to protect the video output borders for analog VGA dacs (outside the active video area, the RGB level must be always black), I usually would have something like another 16 programmable of these X&Y on and off output flags which may be used to position sprites or superimposed hardware video windows.  Among these 16, which may be positioned after the active video region output, allotting a time slot which may be used to signal memory access cycles to fill your audio DAC buffer, or signal load a new set of X&Y video memory pointers from memory which change the beginning video read address of the next line of video allowing you to dynamically have a new video address and video mode on each new video line.  (EG like the Atari 800 display list which allows for a few lines of text mode, then a few with graphics, then more text at a different resolution, or Amiga pulldown screens with a vertically scroll-able window on top of another, each with a different graphics mode pointing to somewhere different in memory.)

Also, in my designs, I call the 'pix_enable' pclk_ena, or pena, even though I expect the reset to activate even if the pena is held low.

If you still directly want to use you h_count and v_count as reference pixel counters and get rid of the ensuing subtraction math to improve FMAX, I would move your hsync and vsync to the end of your counters so that 0 through 639 and 0 through 479 are passed through without any math while the blank front & back porches with syncs come at then end after pixel 640 and line 480.  I personally still prefer the 1 bit enables which can actually tell you ensuing logic when to start and stop reading, or when there is free time to read memory for other purposes.  With your current code, your logic will continue reading pixel 0x0 whenever there is no video being outputted.
« Last Edit: November 01, 2019, 06:59:10 am by BrianHG »
 

Offline Berni

  • Super Contributor
  • ***
  • Posts: 5031
  • Country: si
Re: FPGA VGA Controller for 8-bit computer
« Reply #174 on: October 31, 2019, 11:34:17 pm »
Yeah those are just warnings about a few things.  By default numbers are 32bit so technically you should use the 1'b1 to make a 1bit number, but functionally there is no difference because it gets truncated to 1 bit anyway.

The other warning about no driver is because you are only setting the bit 1 of your RGB output ports while bit 0 is never set to anything. This is usually a mistake so it warns about it. Since it does not know what to do with it it sets them to be 0 and also warns that it did that.

HDL compilers love to spit out warnings about all sorts of things so you usually won't get a zero warning zero error compilation like you tend to strive for in most other programming, If nothing else it will spit out a warning that it is not fully licensed.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf